home *** CD-ROM | disk | FTP | other *** search
/ Power Programmierung 2 / Power-Programmierung CD 2 (Tewi)(1994).iso / gnu / djgpp / src / gas-211 / gas / config / obj-vms.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-05-30  |  134.3 KB  |  5,619 lines

  1. /* vms.c -- Write out a VAX/VMS object file
  2.    Copyright (C) 1987, 1988, 1992 Free Software Foundation, Inc.
  3.  
  4. This file is part of GAS, the GNU Assembler.
  5.  
  6. GAS is free software; you can redistribute it and/or modify
  7. it under the terms of the GNU General Public License as published by
  8. the Free Software Foundation; either version 2, or (at your option)
  9. any later version.
  10.  
  11. GAS is distributed in the hope that it will be useful,
  12. but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14. GNU General Public License for more details.
  15.  
  16. You should have received a copy of the GNU General Public License
  17. along with GAS; see the file COPYING.  If not, write to
  18. the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
  19.  
  20. /* Written by David L. Kashtan */
  21. /* Modified by Eric Youngdale to write VMS debug records for program
  22.    variables */
  23. #include "as.h"
  24. #include "config.h"
  25. #include "subsegs.h"
  26. #include "obstack.h"
  27.  
  28. /* What we do if there is a goof. */
  29. #define error as_fatal
  30.  
  31. #ifdef HO_VMS            /* These are of no use if we are cross assembling. */
  32. #include <fab.h>        /* Define File Access Block      */
  33. #include <nam.h>        /* Define NAM Block          */
  34. #include <xab.h>        /* Define XAB - all different types*/
  35. #endif
  36. /*
  37.  *    Version string of the compiler that produced the code we are
  38.  *    assembling.  (And this assembler, if we do not have compiler info.)
  39.  */
  40. char *compiler_version_string;
  41.  
  42. /* Flag that determines how we map names.  This takes several values, and
  43.  * is set with the -h switch.  A value of zero implies names should be 
  44.  * upper case, and the presence of the -h switch inhibits the case hack.
  45.  * No -h switch at all sets vms_name_mapping to 0, and allows case hacking.
  46.  * A value of 2 (set with -h2) implies names should be
  47.  * all lower case, with no case hack.  A value of 3 (set with -h3) implies
  48.  * that case should be preserved.  */
  49.  
  50. /* If the -+ switch is given, then the hash is appended to any name that is
  51.  * longer than 31 characters, irregardless of the setting of the -h switch.
  52.  */
  53.  
  54. char vms_name_mapping = 0;
  55.  
  56.  
  57. extern char *strchr ();
  58. extern char *myname;
  59. static symbolS *Entry_Point_Symbol = 0;    /* Pointer to "_main" */
  60.  
  61. /*
  62.  *    We augment the "gas" symbol structure with this
  63.  */
  64. struct VMS_Symbol
  65. {
  66.   struct VMS_Symbol *Next;
  67.   struct symbol *Symbol;
  68.   int Size;
  69.   int Psect_Index;
  70.   int Psect_Offset;
  71. };
  72. struct VMS_Symbol *VMS_Symbols = 0;
  73.  
  74. /* We need this to keep track of the various input files, so that we can
  75.  * give the debugger the correct source line.
  76.  */
  77.  
  78. struct input_file
  79. {
  80.   struct input_file *next;
  81.   struct input_file *same_file_fpnt;
  82.   int file_number;
  83.   int max_line;
  84.   int min_line;
  85.   int offset;
  86.   char flag;
  87.   char *name;
  88.   symbolS *spnt;
  89. };
  90.  
  91. static struct input_file *file_root = (struct input_file *) NULL;
  92.  
  93.  
  94. static struct input_file *find_file PARAMS ((symbolS *));
  95.  
  96. /*
  97.  * This enum is used to keep track of the various types of variables that
  98.  * may be present.
  99.  */
  100.  
  101. enum advanced_type
  102. {
  103.   BASIC, POINTER, ARRAY, ENUM, STRUCT, UNION, FUNCTION, VOID, ALIAS, UNKNOWN
  104. };
  105.  
  106. /*
  107.  * This structure contains the information from the stabs directives, and the
  108.  * information is filled in by VMS_typedef_parse.  Everything that is needed
  109.  * to generate the debugging record for a given symbol is present here.
  110.  * This could be done more efficiently, using nested struct/unions, but for now
  111.  * I am happy that it works.
  112.  */
  113. struct VMS_DBG_Symbol
  114. {
  115.   struct VMS_DBG_Symbol *next;
  116.   /* description of what this is */
  117.   enum advanced_type advanced;
  118.   /* this record is for this type */
  119.   int dbx_type;
  120.   /* For advanced types this is the type referred to.  I.e., the type
  121.      a pointer points to, or the type of object that makes up an
  122.      array.  */
  123.   int type2;
  124.   /* Use this type when generating a variable def */
  125.   int VMS_type;
  126.   /* used for arrays - this will be present for all */
  127.   int index_min;
  128.   /* entries, but will be meaningless for non-arrays */
  129.   int index_max;
  130.   /* Size in bytes of the data type.  For an array, this is the size
  131.      of one element in the array */
  132.   int data_size;
  133.   /* Number of the structure/union/enum - used for ref */
  134.   int struc_numb;
  135. };
  136.  
  137. struct VMS_DBG_Symbol *VMS_Symbol_type_list;
  138.  
  139. /*
  140.  * We need this structure to keep track of forward references to
  141.  * struct/union/enum that have not been defined yet.  When they are ultimately
  142.  * defined, then we can go back and generate the TIR commands to make a back
  143.  * reference.
  144.  */
  145.  
  146. struct forward_ref
  147. {
  148.   struct forward_ref *next;
  149.   int dbx_type;
  150.   int struc_numb;
  151.   char resolved;
  152. };
  153.  
  154. struct forward_ref *f_ref_root =
  155. {(struct forward_ref *) NULL};
  156.  
  157. /*
  158.  * This routine is used to compare the names of certain types to various
  159.  * fixed types that are known by the debugger.
  160.  */
  161. #define type_check(x)  !strcmp( symbol_name , x )
  162.  
  163. /*
  164.  * This variable is used to keep track of the name of the symbol we are
  165.  * working on while we are parsing the stabs directives.
  166.  */
  167. static char *symbol_name;
  168.  
  169. /* We use this counter to assign numbers to all of the structures, unions
  170.  * and enums that we define.  When we actually declare a variable to the
  171.  * debugger, we can simply do it by number, rather than describing the
  172.  * whole thing each time.
  173.  */
  174.  
  175. static structure_count = 0;
  176.  
  177. /* This variable is used to indicate that we are making the last attempt to
  178.    parse the stabs, and that we should define as much as we can, and ignore 
  179.    the rest */
  180.  
  181. static int final_pass;
  182.  
  183. /* This variable is used to keep track of the current structure number
  184.  * for a given variable.  If this is < 0, that means that the structure
  185.  * has not yet been defined to the debugger.  This is still cool, since
  186.  * the VMS object language has ways of fixing things up after the fact,
  187.  * so we just make a note of this, and generate fixups at the end.
  188.  */
  189. static int struct_number;
  190.  
  191.  
  192. /*
  193.  * Variable descriptors are used tell the debugger the data types of certain
  194.  * more complicated variables (basically anything involving a structure,
  195.  * union, enum, array or pointer).  Some non-pointer variables of the
  196.  * basic types that the debugger knows about do not require a variable
  197.  * descriptor.
  198.  *
  199.  * Since it is impossible to have a variable descriptor longer than 128
  200.  * bytes by virtue of the way that the VMS object language is set up,
  201.  * it makes not sense to make the arrays any longer than this, or worrying
  202.  * about dynamic sizing of the array.
  203.  *
  204.  * These are the arrays and counters that we use to build a variable
  205.  * descriptor.
  206.  */
  207.  
  208. #define MAX_DEBUG_RECORD 128
  209. static char Local[MAX_DEBUG_RECORD];    /* buffer for variable descriptor */
  210. static char Asuffix[MAX_DEBUG_RECORD];    /* buffer for array descriptor */
  211. static int Lpnt;        /* index into Local */
  212. static int Apoint;        /* index into Asuffix */
  213. static char overflow;        /* flag to indicate we have written too much*/
  214. static int total_len;        /* used to calculate the total length of variable
  215.                 descriptor plus array descriptor - used for len byte*/
  216.  
  217. /* Flag if we have told user about finding global constants in the text
  218.    section. */
  219. static gave_compiler_message = 0;
  220.  
  221. /* A pointer to the current routine that we are working on.  */
  222.  
  223. static symbolS *Current_Routine;
  224.  
  225. /* The psect number for $code a.k.a. the text section. */
  226.  
  227. static int Text_Psect;
  228.  
  229.  
  230. /*
  231.  *    Global data (Object records limited to 512 bytes by VAX-11 "C" runtime)
  232.  */
  233. static int VMS_Object_File_FD;    /* File Descriptor for object file */
  234. static char Object_Record_Buffer[512];    /* Buffer for object file records  */
  235. static int Object_Record_Offset;/* Offset to end of data       */
  236. static int Current_Object_Record_Type;    /* Type of record in above       */
  237.  
  238. /*
  239.  *    Macros for moving data around.  Must work on big-endian systems.
  240.  */
  241. #ifdef HO_VMS  /* These are more efficient for VMS->VMS systems */
  242. #define COPY_LONG(dest,val) {*(long *) dest = val; }
  243. #define COPY_SHORT(dest,val) {*(short *) dest = val; }
  244. #else
  245. #define    COPY_LONG(dest,val) { md_number_to_chars(dest, val, 4); }
  246. #define    COPY_SHORT(dest,val) { md_number_to_chars(dest, val, 2); }
  247. #endif
  248. /*
  249.  *    Macros for placing data into the object record buffer
  250.  */
  251.  
  252. #define    PUT_LONG(val) \
  253. { md_number_to_chars(Object_Record_Buffer + \
  254.              Object_Record_Offset, val, 4); \
  255.              Object_Record_Offset += 4; }
  256.  
  257. #define    PUT_SHORT(val) \
  258. { md_number_to_chars(Object_Record_Buffer + \
  259.              Object_Record_Offset, val, 2); \
  260.              Object_Record_Offset += 2; }
  261.  
  262. #define    PUT_CHAR(val)    Object_Record_Buffer[Object_Record_Offset++] = val
  263.  
  264. #define    PUT_COUNTED_STRING(cp) {\
  265.             register char *p = cp; \
  266.             PUT_CHAR(strlen(p)); \
  267.             while (*p) PUT_CHAR(*p++);}
  268.  
  269. /*
  270.  *    Macro for determining if a Name has psect attributes attached
  271.  *    to it.
  272.  */
  273. #define    PSECT_ATTRIBUTES_STRING        "$$PsectAttributes_"
  274. #define    PSECT_ATTRIBUTES_STRING_LENGTH    18
  275.  
  276. #define    HAS_PSECT_ATTRIBUTES(Name) \
  277.         (strncmp((Name[0] == '_' ? Name + 1 : Name), \
  278.          PSECT_ATTRIBUTES_STRING, \
  279.          PSECT_ATTRIBUTES_STRING_LENGTH) == 0)
  280.  
  281.  
  282.  /* in: segT   out: N_TYPE bits */
  283. const short seg_N_TYPE[] =
  284. {
  285.   N_ABS,
  286.   N_TEXT,
  287.   N_DATA,
  288.   N_BSS,
  289.   N_UNDF,            /* unknown */
  290.   N_UNDF,            /* absent */
  291.   N_UNDF,            /* pass1 */
  292.   N_UNDF,            /* error */
  293.   N_UNDF,            /* bignum/flonum */
  294.   N_UNDF,            /* difference */
  295.   N_UNDF,            /* debug */
  296.   N_UNDF,            /* ntv */
  297.   N_UNDF,            /* ptv */
  298.   N_REGISTER,            /* register */
  299. };
  300.  
  301. const segT N_TYPE_seg[N_TYPE + 2] =
  302. {                /* N_TYPE == 0x1E = 32-2 */
  303.   SEG_UNKNOWN,            /* N_UNDF == 0 */
  304.   SEG_GOOF,
  305.   SEG_ABSOLUTE,            /* N_ABS == 2 */
  306.   SEG_GOOF,
  307.   SEG_TEXT,            /* N_TEXT == 4 */
  308.   SEG_GOOF,
  309.   SEG_DATA,            /* N_DATA == 6 */
  310.   SEG_GOOF,
  311.   SEG_BSS,            /* N_BSS == 8 */
  312.   SEG_GOOF,
  313.   SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF,
  314.   SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF,
  315.   SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF,
  316.   SEG_REGISTER,            /* dummy N_REGISTER for regs = 30 */
  317.   SEG_GOOF,
  318. };
  319.  
  320.  
  321. /* The following code defines the special types of pseudo-ops that we
  322.  *  use with VMS.
  323.  */
  324.  
  325. char const_flag = 0;
  326.  
  327. void
  328. s_const ()
  329. {
  330.   register int temp;
  331.  
  332.   temp = get_absolute_expression ();
  333.   subseg_new (SEG_DATA, (subsegT) temp);
  334.   const_flag = 1;
  335.   demand_empty_rest_of_line ();
  336. }
  337.  
  338. /*
  339.  *            stab()
  340.  *
  341.  * Handle .stabX directives, which used to be open-coded.
  342.  * So much creeping featurism overloaded the semantics that we decided
  343.  * to put all .stabX thinking in one place. Here.
  344.  *
  345.  * We try to make any .stabX directive legal. Other people's AS will often
  346.  * do assembly-time consistency checks: eg assigning meaning to n_type bits
  347.  * and "protecting" you from setting them to certain values. (They also zero
  348.  * certain bits before emitting symbols. Tut tut.)
  349.  *
  350.  * If an expression is not absolute we either gripe or use the relocation
  351.  * information. Other people's assemblers silently forget information they
  352.  * don't need and invent information they need that you didn't supply.
  353.  *
  354.  * .stabX directives always make a symbol table entry. It may be junk if
  355.  * the rest of your .stabX directive is malformed.
  356.  */
  357. static void
  358. obj_aout_stab (what)
  359.      int what;
  360. {
  361. #ifndef NO_LISTING
  362.     extern int listing;
  363. #endif /* NO_LISTING */
  364.  
  365.   register symbolS *symbolP = 0;
  366.   register char *string;
  367.   int saved_type = 0;
  368.   int length;
  369.   int goof;            /* TRUE if we have aborted. */
  370.   long longint;
  371.  
  372. /*
  373.  * Enter with input_line_pointer pointing past .stabX and any following
  374.  * whitespace.
  375.  */
  376.   goof = 0;            /* JF who forgot this?? */
  377.   if (what == 's')
  378.     {
  379.       string = demand_copy_C_string (&length);
  380.       SKIP_WHITESPACE ();
  381.       if (*input_line_pointer == ',')
  382.     input_line_pointer++;
  383.       else
  384.     {
  385.       as_bad ("I need a comma after symbol's name");
  386.       goof = 1;
  387.     }
  388.     }
  389.   else
  390.     string = "";
  391.  
  392. /*
  393.  * Input_line_pointer->after ','.  String->symbol name.
  394.  */
  395.   if (!goof)
  396.     {
  397.       symbolP = symbol_new (string,
  398.                 SEG_UNKNOWN,
  399.                 0,
  400.                 (struct frag *) 0);
  401.       switch (what)
  402.     {
  403.     case 'd':
  404.       S_SET_NAME (symbolP, NULL);    /* .stabd feature. */
  405.       S_SET_VALUE (symbolP, obstack_next_free (&frags) - frag_now->fr_literal);
  406.       symbolP->sy_frag = frag_now;
  407.       break;
  408.  
  409.     case 'n':
  410.       symbolP->sy_frag = &zero_address_frag;
  411.       break;
  412.  
  413.     case 's':
  414.       symbolP->sy_frag = &zero_address_frag;
  415.       break;
  416.  
  417.     default:
  418.       BAD_CASE (what);
  419.       break;
  420.     }
  421.  
  422.       if (get_absolute_expression_and_terminator (&longint) == ',')
  423.     symbolP->sy_symbol.n_type = saved_type = longint;
  424.       else
  425.     {
  426.       as_bad ("I want a comma after the n_type expression");
  427.       goof = 1;
  428.       input_line_pointer--;    /* Backup over a non-',' char. */
  429.     }
  430.     }
  431.  
  432.   if (!goof)
  433.     {
  434.       if (get_absolute_expression_and_terminator (&longint) == ',')
  435.     S_SET_OTHER (symbolP, longint);
  436.       else
  437.     {
  438.       as_bad ("I want a comma after the n_other expression");
  439.       goof = 1;
  440.       input_line_pointer--;    /* Backup over a non-',' char. */
  441.     }
  442.     }
  443.  
  444.   if (!goof)
  445.     {
  446.       S_SET_DESC (symbolP, get_absolute_expression ());
  447.       if (what == 's' || what == 'n')
  448.     {
  449.       if (*input_line_pointer != ',')
  450.         {
  451.           as_bad ("I want a comma after the n_desc expression");
  452.           goof = 1;
  453.         }
  454.       else
  455.         {
  456.           input_line_pointer++;
  457.         }
  458.     }
  459.     }
  460.  
  461.   if ((!goof) && (what == 's' || what == 'n'))
  462.     {
  463.       pseudo_set (symbolP);
  464.       symbolP->sy_symbol.n_type = saved_type;
  465.     }
  466.  
  467. #ifndef NO_LISTING
  468.     if (listing && !goof) 
  469.         {
  470.             if (symbolP->sy_symbol.n_type == N_SLINE) 
  471.             {
  472.                 
  473.                 listing_source_line(symbolP->sy_symbol.n_desc);
  474.             }
  475.             else if (symbolP->sy_symbol.n_type == N_SO
  476.                  || symbolP->sy_symbol.n_type == N_SOL) 
  477.             {
  478.                 listing_source_file(string);
  479.             }              
  480.         }
  481. #endif  
  482.  
  483.   if (goof)
  484.     ignore_rest_of_line ();
  485.   else
  486.     demand_empty_rest_of_line ();
  487. }                /* obj_aout_stab() */
  488.  
  489. const pseudo_typeS obj_pseudo_table[] =
  490. {
  491.   {"stabd", obj_aout_stab, 'd'},/* stabs */
  492.   {"stabn", obj_aout_stab, 'n'},/* stabs */
  493.   {"stabs", obj_aout_stab, 's'},/* stabs */
  494.   {"const", s_const, 0},
  495.   {0, 0, 0},
  496.  
  497. };                /* obj_pseudo_table */
  498.  
  499. int
  500. vms_resolve_symbol_redef (sym)
  501.      symbolS *sym;
  502. {
  503.   /*
  504.    *    If the new symbol is .comm AND it has a size of zero,
  505.    *    we ignore it (i.e. the old symbol overrides it)
  506.    */
  507.   if ((SEGMENT_TO_SYMBOL_TYPE ((int) now_seg) == (N_UNDF | N_EXT)) &&
  508.       ((obstack_next_free (&frags) - frag_now->fr_literal) == 0))
  509.     {
  510.       as_warn ("compiler emitted zero-size common symbol `%s' already defined",
  511.            S_GET_NAME (sym));
  512.       return 1;
  513.     }
  514.   /*
  515.    *    If the old symbol is .comm and it has a size of zero,
  516.    *    we override it with the new symbol value.
  517.    */
  518.   if (S_IS_EXTERNAL(sym) &&  S_IS_DEFINED(sym)
  519.       && (S_GET_VALUE(sym) == 0))
  520.     {
  521.       as_warn ("compiler redefined zero-size common symbol `%s'",
  522.            S_GET_NAME (sym));
  523.       sym->sy_frag  = frag_now;
  524.       S_GET_OTHER(sym) = const_flag;
  525.       S_SET_VALUE(sym, obstack_next_free(& frags) - frag_now->fr_literal);
  526.       /* Keep N_EXT bit.  */
  527.       sym->sy_symbol.n_type |= SEGMENT_TO_SYMBOL_TYPE((int) now_seg);
  528.       return 1;
  529.     }
  530.  
  531.   return 0;
  532. }
  533.  
  534.  
  535. void 
  536. obj_read_begin_hook ()
  537. {
  538.   return;
  539. }                /* obj_read_begin_hook() */
  540.  
  541. void 
  542. obj_crawl_symbol_chain (headers)
  543.      object_headers *headers;
  544. {
  545.   symbolS *symbolP;
  546.   symbolS **symbolPP;
  547.   int symbol_number = 0;
  548.  
  549.   /* JF deal with forward references first... */
  550.   for (symbolP = symbol_rootP; symbolP; symbolP = symbol_next (symbolP))
  551.     {
  552.       if (symbolP->sy_forward)
  553.     {
  554.       S_SET_VALUE (symbolP, S_GET_VALUE (symbolP)
  555.                + S_GET_VALUE (symbolP->sy_forward)
  556.                + symbolP->sy_forward->sy_frag->fr_address);
  557.       symbolP->sy_forward = 0;
  558.     }            /* if it has a forward reference */
  559.     }                /* walk the symbol chain */
  560.  
  561.   {                /* crawl symbol table */
  562.     register int symbol_number = 0;
  563.  
  564.     {
  565.       symbolPP = &symbol_rootP;    /* -> last symbol chain link. */
  566.       while ((symbolP = *symbolPP) != NULL)
  567.     {
  568.       S_GET_VALUE (symbolP) += symbolP->sy_frag->fr_address;
  569.  
  570.       /* OK, here is how we decide which symbols go out into the
  571.          brave new symtab.  Symbols that do are:
  572.         
  573.          * symbols with no name (stabd's?)
  574.          * symbols with debug info in their N_TYPE
  575.         
  576.          Symbols that don't are:
  577.          * symbols that are registers
  578.          * symbols with \1 as their 3rd character (numeric labels)
  579.          * "local labels" as defined by S_LOCAL_NAME(name)
  580.          if the -L switch was passed to gas.
  581.         
  582.          All other symbols are output.  We complain if a deleted
  583.          symbol was marked external.  */
  584.  
  585.  
  586.       if (!S_IS_REGISTER (symbolP))
  587.         {
  588.           symbolP->sy_name_offset = 0;
  589.           symbolPP = &(symbol_next (symbolP));
  590.         }
  591.       else
  592.         {
  593.           if (S_IS_EXTERNAL (symbolP) || !S_IS_DEFINED (symbolP))
  594.         {
  595.           as_bad ("Local symbol %s never defined", S_GET_NAME (symbolP));
  596.         }        /* oops. */
  597.  
  598.         }            /* if this symbol should be in the output */
  599.     }            /* for each symbol */
  600.     }
  601.     H_SET_STRING_SIZE (headers, string_byte_count);
  602.     H_SET_SYMBOL_TABLE_SIZE (headers, symbol_number);
  603.   }                /* crawl symbol table */
  604.  
  605. }                /* obj_crawl_symbol_chain() */
  606.  
  607.  
  608.  /****** VMS OBJECT FILE HACKING ROUTINES *******/
  609.  
  610.  
  611. /*
  612.  *    Create the VMS object file
  613.  */
  614. static
  615. Create_VMS_Object_File ()
  616. {
  617. #if    defined(eunice) || !defined(HO_VMS)
  618.   VMS_Object_File_FD = creat (out_file_name, 0777, "var");
  619. #else    /* eunice */
  620.   VMS_Object_File_FD = creat (out_file_name, 0, "rfm=var", 
  621.                  "mbc=16", "deq=64", "fop=tef", "shr=nil");
  622. #endif    /* eunice */
  623.   /*
  624.    *    Deal with errors
  625.    */
  626.   if (VMS_Object_File_FD < 0)
  627.     {
  628.       char Error_Line[256];
  629.  
  630.       sprintf (Error_Line, "Couldn't create VMS object file \"%s\"",
  631.            out_file_name);
  632.       error (Error_Line);
  633.     }
  634.   /*
  635.    *    Initialize object file hacking variables
  636.    */
  637.   Object_Record_Offset = 0;
  638.   Current_Object_Record_Type = -1;
  639. }
  640.  
  641.  
  642. /*
  643.  *    Flush the object record buffer to the object file
  644.  */
  645. static
  646. Flush_VMS_Object_Record_Buffer ()
  647. {
  648.   int i;
  649.   short int zero;
  650.   int RecLen;
  651.   /*
  652.    *    If the buffer is empty, we are done
  653.    */
  654.   if (Object_Record_Offset == 0)
  655.     return;
  656.   /*
  657.    *    Write the data to the file
  658.    */
  659. #ifndef HO_VMS            /* For cross-assembly purposes. */
  660.   md_number_to_chars((char *) &RecLen, Object_Record_Offset, 2);
  661.   i = write (VMS_Object_File_FD, &RecLen, 2);
  662. #endif /* not HO_VMS */
  663.   i = write (VMS_Object_File_FD,
  664.          Object_Record_Buffer,
  665.          Object_Record_Offset);
  666.   if (i != Object_Record_Offset)
  667.     error ("I/O error writing VMS object file");
  668. #ifndef HO_VMS            /* When cross-assembling, we need to pad the record to an even
  669.                         number of bytes. */
  670.   /* pad it if needed */
  671.   zero = 0;
  672.   if (Object_Record_Offset & 1 != 0)
  673.     write (VMS_Object_File_FD, &zero, 1);
  674. #endif /* not HO_VMS */
  675.   /*
  676.    *    The buffer is now empty
  677.    */
  678.   Object_Record_Offset = 0;
  679. }
  680.  
  681.  
  682. /*
  683.  *    Declare a particular type of object file record
  684.  */
  685. static
  686. Set_VMS_Object_File_Record (Type)
  687.      int Type;
  688. {
  689.   /*
  690.    *    If the type matches, we are done
  691.    */
  692.   if (Type == Current_Object_Record_Type)
  693.     return;
  694.   /*
  695.    *    Otherwise: flush the buffer
  696.    */
  697.   Flush_VMS_Object_Record_Buffer ();
  698.   /*
  699.    *    Set the new type
  700.    */
  701.   Current_Object_Record_Type = Type;
  702. }
  703.  
  704.  
  705.  
  706. /*
  707.  *    Close the VMS Object file
  708.  */
  709. static
  710. Close_VMS_Object_File ()
  711. {
  712.   short int m_one = -1;
  713. #ifndef HO_VMS            /* For cross-assembly purposes. */
  714. /* Write a 0xffff into the file, which means "End of File" */
  715.   write (VMS_Object_File_FD, &m_one, 2);
  716. #endif /* not HO_VMS */
  717.   close (VMS_Object_File_FD);
  718. }
  719.  
  720.  
  721. /*
  722.  *    Store immediate data in current Psect
  723.  */
  724. static
  725. VMS_Store_Immediate_Data (Pointer, Size, Record_Type)
  726.      CONST char *Pointer;
  727.      int Size;
  728.      int Record_Type;
  729. {
  730.   register int i;
  731.  
  732.   /*
  733.    *    We are writing a "Record_Type" record
  734.    */
  735.   Set_VMS_Object_File_Record (Record_Type);
  736.   /*
  737.    *    We can only store 128 bytes at a time
  738.    */
  739.   while (Size > 0)
  740.     {
  741.       /*
  742.        *    Store a maximum of 128 bytes
  743.        */
  744.       i = (Size > 128) ? 128 : Size;
  745.       Size -= i;
  746.       /*
  747.        *    If we cannot accommodate this record, flush the
  748.        *    buffer.
  749.        */
  750.       if ((Object_Record_Offset + i + 1) >=
  751.       sizeof (Object_Record_Buffer))
  752.     Flush_VMS_Object_Record_Buffer ();
  753.       /*
  754.        *    If the buffer is empty we must insert record type
  755.        */
  756.       if (Object_Record_Offset == 0)
  757.     PUT_CHAR (Record_Type);
  758.       /*
  759.        *    Store the count
  760.        */
  761.       PUT_CHAR (-i & 0xff);
  762.       /*
  763.        *    Store the data
  764.        */
  765.       while (--i >= 0)
  766.     PUT_CHAR (*Pointer++);
  767.       /*
  768.        *    Flush the buffer if it is more than 75% full
  769.        */
  770.       if (Object_Record_Offset >
  771.       (sizeof (Object_Record_Buffer) * 3 / 4))
  772.     Flush_VMS_Object_Record_Buffer ();
  773.     }
  774. }
  775.  
  776. /*
  777.  *    Make a data reference
  778.  */
  779. static
  780. VMS_Set_Data (Psect_Index, Offset, Record_Type, Force)
  781.      int Psect_Index;
  782.      int Offset;
  783.      int Record_Type;
  784.      int Force;
  785. {
  786.   /*
  787.    *    We are writing a "Record_Type" record
  788.    */
  789.   Set_VMS_Object_File_Record (Record_Type);
  790.   /*
  791.    *    If the buffer is empty we must insert the record type
  792.    */
  793.   if (Object_Record_Offset == 0)
  794.     PUT_CHAR (Record_Type);
  795.   /*
  796.    *    Stack the Psect base + Longword Offset
  797.    */
  798.   if (Force == 1)
  799.     {
  800.       if (Psect_Index > 127)
  801.     {
  802.       PUT_CHAR (TIR_S_C_STA_WPL);
  803.       PUT_SHORT (Psect_Index);
  804.       PUT_LONG (Offset);
  805.     }
  806.       else
  807.     {
  808.       PUT_CHAR (TIR_S_C_STA_PL);
  809.       PUT_CHAR (Psect_Index);
  810.       PUT_LONG (Offset);
  811.     }
  812.     }
  813.   else
  814.     {
  815.       if (Offset > 32767)
  816.     {
  817.       PUT_CHAR (TIR_S_C_STA_WPL);
  818.       PUT_SHORT (Psect_Index);
  819.       PUT_LONG (Offset);
  820.     }
  821.       else if (Offset > 127)
  822.     {
  823.       PUT_CHAR (TIR_S_C_STA_WPW);
  824.       PUT_SHORT (Psect_Index);
  825.       PUT_SHORT (Offset);
  826.     }
  827.       else
  828.     {
  829.       PUT_CHAR (TIR_S_C_STA_WPB);
  830.       PUT_SHORT (Psect_Index);
  831.       PUT_CHAR (Offset);
  832.     };
  833.     };
  834.   /*
  835.    *    Set relocation base
  836.    */
  837.   PUT_CHAR (TIR_S_C_STO_PIDR);
  838.   /*
  839.    *    Flush the buffer if it is more than 75% full
  840.    */
  841.   if (Object_Record_Offset >
  842.       (sizeof (Object_Record_Buffer) * 3 / 4))
  843.     Flush_VMS_Object_Record_Buffer ();
  844. }
  845.  
  846. /*
  847.  *    Make a debugger reference to a struct, union or enum.
  848.  */
  849. static
  850. VMS_Store_Struct (Struct_Index)
  851.      int Struct_Index;
  852. {
  853.   /*
  854.    *    We are writing a "OBJ_S_C_DBG" record
  855.    */
  856.   Set_VMS_Object_File_Record (OBJ_S_C_DBG);
  857.   /*
  858.    *    If the buffer is empty we must insert the record type
  859.    */
  860.   if (Object_Record_Offset == 0)
  861.     PUT_CHAR (OBJ_S_C_DBG);
  862.   PUT_CHAR (TIR_S_C_STA_UW);
  863.   PUT_SHORT (Struct_Index);
  864.   PUT_CHAR (TIR_S_C_CTL_STKDL);
  865.   PUT_CHAR (TIR_S_C_STO_L);
  866.   /*
  867.    *    Flush the buffer if it is more than 75% full
  868.    */
  869.   if (Object_Record_Offset >
  870.       (sizeof (Object_Record_Buffer) * 3 / 4))
  871.     Flush_VMS_Object_Record_Buffer ();
  872. }
  873.  
  874. /*
  875.  *    Make a debugger reference to partially define a struct, union or enum.
  876.  */
  877. static
  878. VMS_Def_Struct (Struct_Index)
  879.      int Struct_Index;
  880. {
  881.   /*
  882.    *    We are writing a "OBJ_S_C_DBG" record
  883.    */
  884.   Set_VMS_Object_File_Record (OBJ_S_C_DBG);
  885.   /*
  886.    *    If the buffer is empty we must insert the record type
  887.    */
  888.   if (Object_Record_Offset == 0)
  889.     PUT_CHAR (OBJ_S_C_DBG);
  890.   PUT_CHAR (TIR_S_C_STA_UW);
  891.   PUT_SHORT (Struct_Index);
  892.   PUT_CHAR (TIR_S_C_CTL_DFLOC);
  893.   /*
  894.    *    Flush the buffer if it is more than 75% full
  895.    */
  896.   if (Object_Record_Offset >
  897.       (sizeof (Object_Record_Buffer) * 3 / 4))
  898.     Flush_VMS_Object_Record_Buffer ();
  899. }
  900.  
  901. static
  902. VMS_Set_Struct (Struct_Index)
  903.      int Struct_Index;
  904. {                /* see previous functions for comments */
  905.   Set_VMS_Object_File_Record (OBJ_S_C_DBG);
  906.   if (Object_Record_Offset == 0)
  907.     PUT_CHAR (OBJ_S_C_DBG);
  908.   PUT_CHAR (TIR_S_C_STA_UW);
  909.   PUT_SHORT (Struct_Index);
  910.   PUT_CHAR (TIR_S_C_CTL_STLOC);
  911.   if (Object_Record_Offset >
  912.       (sizeof (Object_Record_Buffer) * 3 / 4))
  913.     Flush_VMS_Object_Record_Buffer ();
  914. }
  915.  
  916. /*
  917.  *    Write the Traceback Module Begin record
  918.  */
  919. static
  920. VMS_TBT_Module_Begin ()
  921. {
  922.   register char *cp, *cp1;
  923.   int Size;
  924.   char Module_Name[256];
  925.   char Local[256];
  926.  
  927.   /*
  928.    *    Get module name (the FILENAME part of the object file)
  929.    */
  930.   cp = out_file_name;
  931.   cp1 = Module_Name;
  932.   while (*cp)
  933.     {
  934.       if ((*cp == ']') || (*cp == '>') ||
  935.       (*cp == ':') || (*cp == '/'))
  936.     {
  937.       cp1 = Module_Name;
  938.       cp++;
  939.       continue;
  940.     }
  941.       *cp1++ = islower (*cp) ? toupper (*cp++) : *cp++;
  942.     }
  943.   *cp1 = 0;
  944.   /*
  945.    *    Limit it to 31 characters
  946.    */
  947.   while (--cp1 >= Module_Name)
  948.     if (*cp1 == '.')
  949.       *cp1 = 0;
  950.   if (strlen (Module_Name) > 31)
  951.     {
  952.       if (flagseen['+'])
  953.     printf ("%s: Module name truncated: %s\n", myname, Module_Name);
  954.       Module_Name[31] = 0;
  955.     }
  956.   /*
  957.    *    Arrange to store the data locally (leave room for size byte)
  958.    */
  959.   cp = Local + 1;
  960.   /*
  961.    *    Begin module
  962.    */
  963.   *cp++ = DST_S_C_MODBEG;
  964.   /*
  965.    *    Unused
  966.    */
  967.   *cp++ = 0;
  968.   /*
  969.    *    Language type == "C"
  970.    */
  971.   COPY_LONG (cp, DST_S_C_C);
  972.   cp += sizeof (long);
  973.   /*
  974.    *    Store the module name
  975.    */
  976.   *cp++ = strlen (Module_Name);
  977.   cp1 = Module_Name;
  978.   while (*cp1)
  979.     *cp++ = *cp1++;
  980.   /*
  981.    *    Now we can store the record size
  982.    */
  983.   Size = (cp - Local);
  984.   Local[0] = Size - 1;
  985.   /*
  986.    *    Put it into the object record
  987.    */
  988.   VMS_Store_Immediate_Data (Local, Size, OBJ_S_C_TBT);
  989. }
  990.  
  991.  
  992. /*
  993.  *    Write the Traceback Module End record
  994. */
  995. static
  996. VMS_TBT_Module_End ()
  997. {
  998.   char Local[2];
  999.  
  1000.   /*
  1001.    *    End module
  1002.    */
  1003.   Local[0] = 1;
  1004.   Local[1] = DST_S_C_MODEND;
  1005.   /*
  1006.    *    Put it into the object record
  1007.    */
  1008.   VMS_Store_Immediate_Data (Local, 2, OBJ_S_C_TBT);
  1009. }
  1010.  
  1011.  
  1012. /*
  1013.  *    Write the Traceback Routine Begin record
  1014.  */
  1015. static
  1016. VMS_TBT_Routine_Begin (symbolP, Psect)
  1017.      struct symbol *symbolP;
  1018.      int Psect;
  1019. {
  1020.   register char *cp, *cp1;
  1021.   char *Name;
  1022.   int Offset;
  1023.   int Size;
  1024.   char Local[512];
  1025.  
  1026.   /*
  1027.    *    Strip the leading "_" from the name
  1028.    */
  1029.   Name = S_GET_NAME (symbolP);
  1030.   if (*Name == '_')
  1031.     Name++;
  1032.   /*
  1033.    *    Get the text psect offset
  1034.    */
  1035.   Offset = S_GET_VALUE (symbolP);
  1036.   /*
  1037.    *    Calculate the record size
  1038.    */
  1039.   Size = 1 + 1 + 4 + 1 + strlen (Name);
  1040.   /*
  1041.    *    Record Size
  1042.    */
  1043.   Local[0] = Size;
  1044.   /*
  1045.    *    Begin Routine
  1046.    */
  1047.   Local[1] = DST_S_C_RTNBEG;
  1048.   /*
  1049.    *    Uses CallS/CallG
  1050.    */
  1051.   Local[2] = 0;
  1052.   /*
  1053.    *    Store the data so far
  1054.    */
  1055.   VMS_Store_Immediate_Data (Local, 3, OBJ_S_C_TBT);
  1056.   /*
  1057.    *    Make sure we are still generating a OBJ_S_C_TBT record
  1058.    */
  1059.   if (Object_Record_Offset == 0)
  1060.     PUT_CHAR (OBJ_S_C_TBT);
  1061.   /*
  1062.    *    Now get the symbol address
  1063.    */
  1064.   PUT_CHAR (TIR_S_C_STA_WPL);
  1065.   PUT_SHORT (Psect);
  1066.   PUT_LONG (Offset);
  1067.   /*
  1068.    *    Store the data reference
  1069.    */
  1070.   PUT_CHAR (TIR_S_C_STO_PIDR);
  1071.   /*
  1072.    *    Store the counted string as data
  1073.    */
  1074.   cp = Local;
  1075.   cp1 = Name;
  1076.   Size = strlen (cp1) + 1;
  1077.   *cp++ = Size - 1;
  1078.   while (*cp1)
  1079.     *cp++ = *cp1++;
  1080.   VMS_Store_Immediate_Data (Local, Size, OBJ_S_C_TBT);
  1081. }
  1082.  
  1083.  
  1084. /*
  1085.  *    Write the Traceback Routine End record
  1086.  *     We *must* search the symbol table to find the next routine, since
  1087.  *     the assember has a way of reassembling the symbol table OUT OF ORDER
  1088.  *     Thus the next routine in the symbol list is not necessarily the
  1089.  *    next one in memory.  For debugging to work correctly we must know the
  1090.  *    size of the routine.
  1091.  */
  1092. static
  1093. VMS_TBT_Routine_End (Max_Size, sp)
  1094.      int Max_Size;
  1095.      symbolS *sp;
  1096. {
  1097.   symbolS *symbolP;
  1098.   int Size = 0x7fffffff;
  1099.   char Local[16];
  1100.  
  1101.  
  1102.   for (symbolP = symbol_rootP; symbolP; symbolP = symbol_next (symbolP))
  1103.     {
  1104.       if (!S_IS_DEBUG (symbolP) && S_GET_TYPE (symbolP) == N_TEXT)
  1105.     {
  1106.       if (*S_GET_NAME (symbolP) == 'L')
  1107.         continue;
  1108.       if ((S_GET_VALUE (symbolP) > S_GET_VALUE (sp)) &&
  1109.           (S_GET_VALUE (symbolP) < Size))
  1110.         Size = S_GET_VALUE (symbolP);
  1111.       /* check if gcc_compiled. has size of zero */
  1112.       if ((S_GET_VALUE (symbolP) == S_GET_VALUE (sp)) &&
  1113.           sp != symbolP &&
  1114.           (!strcmp (S_GET_NAME (sp), "gcc_compiled.") ||
  1115.            !strcmp (S_GET_NAME (sp), "gcc2_compiled.")))
  1116.         Size = S_GET_VALUE (symbolP);
  1117.  
  1118.     };
  1119.     };
  1120.   if (Size == 0x7fffffff)
  1121.     Size = Max_Size;
  1122.   Size -= S_GET_VALUE (sp);    /* and get the size of the routine */
  1123.   /*
  1124.    *    Record Size
  1125.    */
  1126.   Local[0] = 6;
  1127.   /*
  1128.    *    End of Routine
  1129.    */
  1130.   Local[1] = DST_S_C_RTNEND;
  1131.   /*
  1132.    *    Unused
  1133.    */
  1134.   Local[2] = 0;
  1135.   /*
  1136.    *    Size of routine
  1137.    */
  1138.   COPY_LONG (&Local[3], Size);
  1139.   /*
  1140.    *    Store the record
  1141.    */
  1142.   VMS_Store_Immediate_Data (Local, 7, OBJ_S_C_TBT);
  1143. }
  1144.  
  1145. /*
  1146.  *    Write the Traceback Block End record
  1147.  */
  1148. static
  1149. VMS_TBT_Block_Begin (symbolP, Psect, Name)
  1150.      struct symbol *symbolP;
  1151.      int Psect;
  1152.      char *Name;
  1153. {
  1154.   register char *cp, *cp1;
  1155.   int Offset;
  1156.   int Size;
  1157.   char Local[512];
  1158.   /*
  1159.    *    Begin block
  1160.    */
  1161.   Size = 1 + 1 + 4 + 1 + strlen (Name);
  1162.   /*
  1163.    *    Record Size
  1164.    */
  1165.   Local[0] = Size;
  1166.   /*
  1167.    *    Begin Block - We simulate with a phony routine
  1168.    */
  1169.   Local[1] = DST_S_C_BLKBEG;
  1170.   /*
  1171.    *    Uses CallS/CallG
  1172.    */
  1173.   Local[2] = 0;
  1174.   /*
  1175.    *    Store the data so far
  1176.    */
  1177.   VMS_Store_Immediate_Data (Local, 3, OBJ_S_C_DBG);
  1178.   /*
  1179.    *    Make sure we are still generating a OBJ_S_C_DBG record
  1180.    */
  1181.   if (Object_Record_Offset == 0)
  1182.     PUT_CHAR (OBJ_S_C_DBG);
  1183.   /*
  1184.    *    Now get the symbol address
  1185.    */
  1186.   PUT_CHAR (TIR_S_C_STA_WPL);
  1187.   PUT_SHORT (Psect);
  1188.   /*
  1189.    *    Get the text psect offset
  1190.    */
  1191.   Offset = S_GET_VALUE (symbolP);
  1192.   PUT_LONG (Offset);
  1193.   /*
  1194.    *    Store the data reference
  1195.    */
  1196.   PUT_CHAR (TIR_S_C_STO_PIDR);
  1197.   /*
  1198.    *    Store the counted string as data
  1199.    */
  1200.   cp = Local;
  1201.   cp1 = Name;
  1202.   Size = strlen (cp1) + 1;
  1203.   *cp++ = Size - 1;
  1204.   while (*cp1)
  1205.     *cp++ = *cp1++;
  1206.   VMS_Store_Immediate_Data (Local, Size, OBJ_S_C_DBG);
  1207. }
  1208.  
  1209.  
  1210. /*
  1211.  *    Write the Traceback Block End record
  1212.  */
  1213. static
  1214. VMS_TBT_Block_End (Size)
  1215.      int Size;
  1216. {
  1217.   char Local[16];
  1218.  
  1219.   /*
  1220.    *    End block - simulate with a phony end routine
  1221.    */
  1222.   Local[0] = 6;
  1223.   Local[1] = DST_S_C_BLKEND;
  1224.   COPY_LONG (&Local[3], Size);
  1225.   /*
  1226.    *    Unused
  1227.    */
  1228.   Local[2] = 0;
  1229.   VMS_Store_Immediate_Data (Local, 7, OBJ_S_C_DBG);
  1230. }
  1231.  
  1232.  
  1233.  
  1234. /*
  1235.  *    Write a Line number / PC correlation record
  1236.  */
  1237. static
  1238. VMS_TBT_Line_PC_Correlation (Line_Number, Offset, Psect, Do_Delta)
  1239.      int Line_Number;
  1240.      int Offset;
  1241.      int Psect;
  1242.      int Do_Delta;
  1243. {
  1244.   register char *cp;
  1245.   char Local[64];
  1246.  
  1247.   /*
  1248. *    If not delta, set our PC/Line number correlation
  1249. */
  1250.   if (Do_Delta == 0)
  1251.     {
  1252.       /*
  1253.        *    Size
  1254.        */
  1255.       Local[0] = 1 + 1 + 2 + 1 + 4;
  1256.       /*
  1257.        *    Line Number/PC correlation
  1258.        */
  1259.       Local[1] = DST_S_C_LINE_NUM;
  1260.       /*
  1261.        *    Set Line number
  1262.        */
  1263.       Local[2] = DST_S_C_SET_LINE_NUM;
  1264.       COPY_SHORT (&Local[3], Line_Number - 1);
  1265.       /*
  1266.        *    Set PC
  1267.        */
  1268.       Local[5] = DST_S_C_SET_ABS_PC;
  1269.       VMS_Store_Immediate_Data (Local, 6, OBJ_S_C_TBT);
  1270.       /*
  1271.        *    Make sure we are still generating a OBJ_S_C_TBT record
  1272.        */
  1273.       if (Object_Record_Offset == 0)
  1274.     PUT_CHAR (OBJ_S_C_TBT);
  1275.       if (Psect < 255)
  1276.     {
  1277.       PUT_CHAR (TIR_S_C_STA_PL);
  1278.       PUT_CHAR (Psect);
  1279.     }
  1280.       else
  1281.     {
  1282.       PUT_CHAR (TIR_S_C_STA_WPL);
  1283.       PUT_SHORT (Psect);
  1284.     }
  1285.       PUT_LONG (Offset);
  1286.       PUT_CHAR (TIR_S_C_STO_PIDR);
  1287.       /*
  1288.        *    Do a PC offset of 0 to register the line number
  1289.        */
  1290.       Local[0] = 2;
  1291.       Local[1] = DST_S_C_LINE_NUM;
  1292.       Local[2] = 0;        /* Increment PC by 0 and register line # */
  1293.       VMS_Store_Immediate_Data (Local, 3, OBJ_S_C_TBT);
  1294.     }
  1295.   else
  1296.     {
  1297.       /*
  1298.        *    If Delta is negative, terminate the line numbers
  1299.        */
  1300.       if (Do_Delta < 0)
  1301.     {
  1302.       Local[0] = 1 + 1 + 4;
  1303.       Local[1] = DST_S_C_LINE_NUM;
  1304.       Local[2] = DST_S_C_TERM_L;
  1305.       COPY_LONG (&Local[3], Offset);
  1306.       VMS_Store_Immediate_Data (Local, 7, OBJ_S_C_TBT);
  1307.       /*
  1308.        *    Done
  1309.        */
  1310.       return;
  1311.     }
  1312.       /*
  1313.        *    Do a PC/Line delta
  1314.        */
  1315.       cp = Local + 1;
  1316.       *cp++ = DST_S_C_LINE_NUM;
  1317.       if (Line_Number > 1)
  1318.     {
  1319.       /*
  1320.        *    We need to increment the line number
  1321.        */
  1322.       if (Line_Number - 1 <= 255)
  1323.         {
  1324.           *cp++ = DST_S_C_INCR_LINUM;
  1325.           *cp++ = Line_Number - 1;
  1326.         }
  1327.       else
  1328.         {
  1329.           *cp++ = DST_S_C_INCR_LINUM_W;
  1330.           COPY_SHORT (cp, Line_Number - 1);
  1331.           cp += sizeof (short);
  1332.         }
  1333.     }
  1334.       /*
  1335.        *    Increment the PC
  1336.        */
  1337.       if (Offset <= 128)
  1338.     {
  1339.       *cp++ = -Offset;
  1340.     }
  1341.       else
  1342.     {
  1343.       if (Offset < 0x10000)
  1344.         {
  1345.           *cp++ = DST_S_C_DELTA_PC_W;
  1346.           COPY_SHORT (cp, Offset);
  1347.           cp += sizeof (short);
  1348.         }
  1349.       else
  1350.         {
  1351.           *cp++ = DST_S_C_DELTA_PC_L;
  1352.           COPY_LONG (cp, Offset);
  1353.           cp += sizeof (long);
  1354.         }
  1355.     }
  1356.       Local[0] = cp - (Local + 1);
  1357.       VMS_Store_Immediate_Data (Local, cp - Local, OBJ_S_C_TBT);
  1358.     }
  1359. }
  1360.  
  1361.  
  1362. /*
  1363.  *    Describe a source file to the debugger
  1364.  */
  1365. static
  1366. VMS_TBT_Source_File (Filename, ID_Number)
  1367.      char *Filename;
  1368.      int ID_Number;
  1369. {
  1370.   register char *cp, *cp1;
  1371.   int Status, i;
  1372.   char Local[512];
  1373. #ifndef HO_VMS            /* Used for cross-assembly */
  1374.   i = strlen (Filename);
  1375. #else /* HO_VMS */
  1376.   static struct FAB Fab;
  1377.   static struct NAM Nam;
  1378.   static struct XABDAT Date_Xab;
  1379.   static struct XABFHC File_Header_Xab;
  1380.   char Es_String[255], Rs_String[255];
  1381.  
  1382.   /*
  1383.    *    Setup the Fab
  1384.    */
  1385.   Fab.fab$b_bid = FAB$C_BID;
  1386.   Fab.fab$b_bln = sizeof (Fab);
  1387.   Fab.fab$l_nam = (&Nam);
  1388.   Fab.fab$l_xab = (char *) &Date_Xab;
  1389.   /*
  1390.    *    Setup the Nam block so we can find out the FULL name
  1391.    *    of the source file.
  1392.    */
  1393.   Nam.nam$b_bid = NAM$C_BID;
  1394.   Nam.nam$b_bln = sizeof (Nam);
  1395.   Nam.nam$l_rsa = Rs_String;
  1396.   Nam.nam$b_rss = sizeof (Rs_String);
  1397.   Nam.nam$l_esa = Es_String;
  1398.   Nam.nam$b_ess = sizeof (Es_String);
  1399.   /*
  1400.    *    Setup the Date and File Header Xabs
  1401.    */
  1402.   Date_Xab.xab$b_cod = XAB$C_DAT;
  1403.   Date_Xab.xab$b_bln = sizeof (Date_Xab);
  1404.   Date_Xab.xab$l_nxt = (char *) &File_Header_Xab;
  1405.   File_Header_Xab.xab$b_cod = XAB$C_FHC;
  1406.   File_Header_Xab.xab$b_bln = sizeof (File_Header_Xab);
  1407.   /*
  1408.    *    Get the file information
  1409.    */
  1410.   Fab.fab$l_fna = Filename;
  1411.   Fab.fab$b_fns = strlen (Filename);
  1412.   Status = sys$open (&Fab);
  1413.   if (!(Status & 1))
  1414.     {
  1415.       printf ("gas: Couldn't find source file \"%s\", Error = %%X%x\n",
  1416.           Filename, Status);
  1417.       return (0);
  1418.     }
  1419.   sys$close (&Fab);
  1420.   /*
  1421.    *    Calculate the size of the resultant string
  1422.    */
  1423.   i = Nam.nam$b_rsl;
  1424. #endif /* HO_VMS */
  1425.   /*
  1426.    *    Size of record
  1427.    */
  1428.   Local[0] = 1 + 1 + 1 + 1 + 1 + 2 + 8 + 4 + 2 + 1 + 1 + i + 1;
  1429.   /*
  1430.    *    Source declaration
  1431.    */
  1432.   Local[1] = DST_S_C_SOURCE;
  1433.   /*
  1434.    *    Make formfeeds count as source records
  1435.    */
  1436.   Local[2] = DST_S_C_SRC_FORMFEED;
  1437.   /*
  1438.    *    Declare source file
  1439.    */
  1440.   Local[3] = DST_S_C_SRC_DECLFILE;
  1441.   Local[4] = 1 + 2 + 8 + 4 + 2 + 1 + 1 + i + 1;
  1442.   cp = Local + 5;
  1443.   /*
  1444.    *    Flags
  1445.    */
  1446.   *cp++ = 0;
  1447.   /*
  1448.    *    File ID
  1449.    */
  1450.   COPY_SHORT (cp, ID_Number);
  1451.   cp += sizeof (short);
  1452. #ifndef HO_VMS
  1453.   /*
  1454.    *    Creation Date.  Unknown, so we fill with zeroes.
  1455.    */
  1456.   *(long *) cp = 0;
  1457.   cp += sizeof (long);
  1458.   *(long *) cp = 0;
  1459.   cp += sizeof (long);
  1460.   /*
  1461.    *    End of file block
  1462.    */
  1463.   *(long *) cp = 0;
  1464.   cp += sizeof (long);
  1465.   /*
  1466.    *    First free byte
  1467.    */
  1468.   *(short *) cp = 0;
  1469.   cp += sizeof (short);
  1470.   /*
  1471.    *    Record format
  1472.    */
  1473.   *cp++ = 0;
  1474.   /*
  1475.    *    Filename
  1476.    */
  1477.   *cp++ = i;
  1478.   cp1 = Filename;
  1479. #else /* Use this code when assembling for VMS on a VMS system */
  1480.   /*
  1481.    *    Creation Date
  1482.    */
  1483.   *(long *) cp = ((long *) &Date_Xab.xab$q_cdt)[0];
  1484.   cp += sizeof (long);
  1485.   *(long *) cp = ((long *) &Date_Xab.xab$q_cdt)[1];
  1486.   cp += sizeof (long);
  1487.   /*
  1488.    *    End of file block
  1489.    */
  1490.   *(long *) cp = File_Header_Xab.xab$l_ebk;
  1491.   cp += sizeof (long);
  1492.   /*
  1493.    *    First free byte
  1494.    */
  1495.   *(short *) cp = File_Header_Xab.xab$w_ffb;
  1496.   cp += sizeof (short);
  1497.   /*
  1498.    *    Record format
  1499.    */
  1500.   *cp++ = File_Header_Xab.xab$b_rfo;
  1501.   /*
  1502.    *    Filename
  1503.    */
  1504.   *cp++ = i;
  1505.   cp1 = Rs_String;
  1506. #endif /* HO_VMS */
  1507.   while (--i >= 0)
  1508.     *cp++ = *cp1++;
  1509.   /*
  1510.    *    Library module name (none)
  1511.    */
  1512.   *cp++ = 0;
  1513.   /*
  1514.    *    Done
  1515.    */
  1516.   VMS_Store_Immediate_Data (Local, cp - Local, OBJ_S_C_TBT);
  1517.   return 1;
  1518. }
  1519.  
  1520.  
  1521. /*
  1522.  *    Give the number of source lines to the debugger
  1523.  */
  1524. static
  1525. VMS_TBT_Source_Lines (ID_Number, Starting_Line_Number, Number_Of_Lines)
  1526.      int ID_Number;
  1527.      int Starting_Line_Number;
  1528.      int Number_Of_Lines;
  1529. {
  1530.   char *cp, *cp1;
  1531.   char Local[16];
  1532.  
  1533.   /*
  1534.    *    Size of record
  1535.    */
  1536.   Local[0] = 1 + 1 + 2 + 1 + 4 + 1 + 2;
  1537.   /*
  1538.    *    Source declaration
  1539.    */
  1540.   Local[1] = DST_S_C_SOURCE;
  1541.   /*
  1542.    *    Set Source File
  1543.    */
  1544.   cp = Local + 2;
  1545.   *cp++ = DST_S_C_SRC_SETFILE;
  1546.   /*
  1547.    *    File ID Number
  1548.    */
  1549.   COPY_SHORT (cp, ID_Number);
  1550.   cp += sizeof (short);
  1551.   /*
  1552.    *    Set record number
  1553.    */
  1554.   *cp++ = DST_S_C_SRC_SETREC_L;
  1555.   COPY_LONG (cp, Starting_Line_Number);
  1556.   cp += sizeof (long);
  1557.   /*
  1558.    *    Define lines
  1559.    */
  1560.   *cp++ = DST_S_C_SRC_DEFLINES_W;
  1561.   COPY_SHORT (cp, Number_Of_Lines);
  1562.   cp += sizeof (short);
  1563.   /*
  1564.    *    Done
  1565.    */
  1566.   VMS_Store_Immediate_Data (Local, cp - Local, OBJ_S_C_TBT);
  1567. }
  1568.  
  1569.  
  1570.  
  1571.  
  1572. /* This routine locates a file in the list of files.  If an entry does not
  1573.  * exist, one is created.  For include files, a new entry is always created
  1574.  * such that inline functions can be properly debugged. */
  1575. static struct input_file *
  1576. find_file (sp)
  1577.      symbolS *sp;
  1578. {
  1579.   struct input_file *same_file;
  1580.   struct input_file *fpnt;
  1581.   same_file = (struct input_file *) NULL;
  1582.   for (fpnt = file_root; fpnt; fpnt = fpnt->next)
  1583.     {
  1584.       if (fpnt == (struct input_file *) NULL)
  1585.     break;
  1586.       if (fpnt->spnt == sp)
  1587.     return fpnt;
  1588.     };
  1589.   for (fpnt = file_root; fpnt; fpnt = fpnt->next)
  1590.     {
  1591.       if (fpnt == (struct input_file *) NULL)
  1592.     break;
  1593.       if (strcmp (S_GET_NAME (sp), fpnt->name) == 0)
  1594.     {
  1595.       if (fpnt->flag == 1)
  1596.         return fpnt;
  1597.       same_file = fpnt;
  1598.       break;
  1599.     };
  1600.     };
  1601.   fpnt = (struct input_file *) malloc (sizeof (struct input_file));
  1602.   if (file_root == (struct input_file *) NULL)
  1603.     file_root = fpnt;
  1604.   else
  1605.     {
  1606.       struct input_file *fpnt1;
  1607.       for (fpnt1 = file_root; fpnt1->next; fpnt1 = fpnt1->next) ;
  1608.       fpnt1->next = fpnt;
  1609.     };
  1610.   fpnt->next = (struct input_file *) NULL;
  1611.   fpnt->name = S_GET_NAME (sp);
  1612.   fpnt->min_line = 0x7fffffff;
  1613.   fpnt->max_line = 0;
  1614.   fpnt->offset = 0;
  1615.   fpnt->flag = 0;
  1616.   fpnt->file_number = 0;
  1617.   fpnt->spnt = sp;
  1618.   fpnt->same_file_fpnt = same_file;
  1619.   return fpnt;
  1620. }
  1621.  
  1622. /*
  1623.  * The following functions and definitions are used to generate object records
  1624.  * that will describe program variables to the VMS debugger.
  1625.  *
  1626.  * This file contains many of the routines needed to output debugging info into
  1627.  * the object file that the VMS debugger needs to understand symbols.  These
  1628.  * routines are called very late in the assembly process, and thus we can be
  1629.  * fairly lax about changing things, since the GSD and the TIR sections have
  1630.  * already been output.
  1631.  */
  1632.  
  1633.  
  1634. /* This routine converts a number string into an integer, and stops when it
  1635.  * sees an invalid character the return value is the address of the character
  1636.  * just past the last character read.  No error is generated.
  1637.  */
  1638. static char *
  1639. cvt_integer (str, rtn)
  1640.      char *str;
  1641.      int *rtn;
  1642. {
  1643.   int ival, neg;
  1644.   neg = *str == '-' ? ++str, -1 : 1;
  1645.   ival = 0;            /* first get the number of the type for dbx */
  1646.   while ((*str <= '9') && (*str >= '0'))
  1647.     ival = 10 * ival + *str++ - '0';
  1648.   *rtn = neg * ival;
  1649.   return str;
  1650. }
  1651.  
  1652. /* this routine fixes the names that are generated by C++, ".this" is a good
  1653.  * example.  The period does not work for the debugger, since it looks like
  1654.  * the syntax for a structure element, and thus it gets mightily confused
  1655.  *
  1656.  * We also use this to strip the PsectAttribute hack from the name before we
  1657.  * write a debugger record */
  1658.  
  1659. static char *
  1660. fix_name (pnt)
  1661.      char *pnt;
  1662. {
  1663.   char *pnt1;
  1664.   /*
  1665.    *    Kill any leading "_"
  1666.    */
  1667.   if (*pnt == '_')
  1668.     pnt++;
  1669.   /*
  1670.    *    Is there a Psect Attribute to skip??
  1671.    */
  1672.   if (HAS_PSECT_ATTRIBUTES (pnt))
  1673.     {
  1674.       /*
  1675.        *    Yes: Skip it
  1676.        */
  1677.       pnt += PSECT_ATTRIBUTES_STRING_LENGTH;
  1678.       while (*pnt)
  1679.     {
  1680.       if ((pnt[0] == '$') && (pnt[1] == '$'))
  1681.         {
  1682.           pnt += 2;
  1683.           break;
  1684.         }
  1685.       pnt++;
  1686.     }
  1687.     }
  1688. /* Here we fix the .this -> $this conversion */
  1689.   for (pnt1 = pnt; *pnt1 != 0; pnt1++)
  1690.     {
  1691.       if (*pnt1 == '.')
  1692.     *pnt1 = '$';
  1693.     };
  1694.   return pnt;
  1695. }
  1696.  
  1697. /* When defining a structure, this routine is called to find the name of
  1698.  * the actual structure.  It is assumed that str points to the equal sign
  1699.  * in the definition, and it moves backward until it finds the start of the
  1700.  * name.  If it finds a 0, then it knows that this structure def is in the
  1701.  * outermost level, and thus symbol_name points to the symbol name.
  1702.  */
  1703. static char *
  1704. get_struct_name (str)
  1705.      char *str;
  1706. {
  1707.   char *pnt;
  1708.   pnt = str;
  1709.   while ((*pnt != ':') && (*pnt != '\0'))
  1710.     pnt--;
  1711.   if (*pnt == '\0')
  1712.     return symbol_name;
  1713.   *pnt-- = '\0';
  1714.   while ((*pnt != ';') && (*pnt != '='))
  1715.     pnt--;
  1716.   if (*pnt == ';')
  1717.     return pnt + 1;
  1718.   while ((*pnt < '0') || (*pnt > '9'))
  1719.     pnt++;
  1720.   while ((*pnt >= '0') && (*pnt <= '9'))
  1721.     pnt++;
  1722.   return pnt;
  1723. }
  1724.  
  1725. /* search symbol list for type number dbx_type.  Return a pointer to struct */
  1726. static struct VMS_DBG_Symbol *
  1727. find_symbol (dbx_type)
  1728.      int dbx_type;
  1729. {
  1730.   struct VMS_DBG_Symbol *spnt;
  1731.   spnt = VMS_Symbol_type_list;
  1732.   while (spnt != (struct VMS_DBG_Symbol *) NULL)
  1733.     {
  1734.       if (spnt->dbx_type == dbx_type)
  1735.     break;
  1736.       spnt = spnt->next;
  1737.     };
  1738.   if (spnt == (struct VMS_DBG_Symbol *) NULL)
  1739.     return 0;            /*Dunno what this is*/
  1740.   if(spnt->advanced == ALIAS)
  1741.     return find_symbol(spnt->type2);
  1742.   return spnt;
  1743. }
  1744.  
  1745.  
  1746. /* this routine puts info into either Local or Asuffix, depending on the sign
  1747.  * of size.  The reason is that it is easier to build the variable descriptor
  1748.  * backwards, while the array descriptor is best built forwards.  In the end
  1749.  * they get put together, if there is not a struct/union/enum along the way
  1750.  */
  1751. static
  1752. push (value, size)
  1753.      int value, size;
  1754. {
  1755.   int i;
  1756.   int size1;
  1757.   size1 = size;
  1758.   if (size < 0)
  1759.     {
  1760.       size1 = -size;
  1761.       if (Lpnt < size1)
  1762.     {
  1763.       overflow = 1;
  1764.       Lpnt = 1;
  1765.       return;
  1766.     };
  1767.       Lpnt -= size1;
  1768.       md_number_to_chars (&Local[Lpnt + 1], value, size1);
  1769.     }
  1770.   else
  1771.     {
  1772.       if (Apoint + size1 >= MAX_DEBUG_RECORD)
  1773.     {
  1774.       overflow = 1;
  1775.       Apoint = MAX_DEBUG_RECORD - 1;
  1776.       return;
  1777.     };
  1778.       md_number_to_chars (&Asuffix[Apoint], value, size1);
  1779.       Apoint += size1;
  1780.     };
  1781. }
  1782.  
  1783. /* this routine generates the array descriptor for a given array */
  1784. static
  1785. array_suffix (spnt2)
  1786.      struct VMS_DBG_Symbol *spnt2;
  1787. {
  1788.   struct VMS_DBG_Symbol *spnt;
  1789.   struct VMS_DBG_Symbol *spnt1;
  1790.   int rank;
  1791.   int total_size;
  1792.   int i;
  1793.   rank = 0;
  1794.   spnt = spnt2;
  1795.   while (spnt->advanced != ARRAY)
  1796.     {
  1797.       spnt = find_symbol (spnt->type2);
  1798.       if (spnt == (struct VMS_DBG_Symbol *) NULL)
  1799.     return;
  1800.     };
  1801.   spnt1 = spnt;
  1802.   spnt1 = spnt;
  1803.   total_size = 1;
  1804.   while (spnt1->advanced == ARRAY)
  1805.     {
  1806.       rank++;
  1807.       total_size *= (spnt1->index_max - spnt1->index_min + 1);
  1808.       spnt1 = find_symbol (spnt1->type2);
  1809.     };
  1810.   total_size = total_size * spnt1->data_size;
  1811.   push (spnt1->data_size, 2);
  1812.   if (spnt1->VMS_type == 0xa3)
  1813.     push (0, 1);
  1814.   else
  1815.     push (spnt1->VMS_type, 1);
  1816.   push (4, 1);
  1817.   for (i = 0; i < 6; i++)
  1818.     push (0, 1);
  1819.   push (0xc0, 1);
  1820.   push (rank, 1);
  1821.   push (total_size, 4);
  1822.   push (0, 4);
  1823.   spnt1 = spnt;
  1824.   while (spnt1->advanced == ARRAY)
  1825.     {
  1826.       push (spnt1->index_max - spnt1->index_min + 1, 4);
  1827.       spnt1 = find_symbol (spnt1->type2);
  1828.     };
  1829.   spnt1 = spnt;
  1830.   while (spnt1->advanced == ARRAY)
  1831.     {
  1832.       push (spnt1->index_min, 4);
  1833.       push (spnt1->index_max, 4);
  1834.       spnt1 = find_symbol (spnt1->type2);
  1835.     };
  1836. }
  1837.  
  1838. /* this routine generates the start of a variable descriptor based upon
  1839.  * a struct/union/enum that has yet to be defined.  We define this spot as
  1840.  * a new location, and save four bytes for the address.  When the struct is
  1841.  * finally defined, then we can go back and plug in the correct address
  1842. */
  1843. static
  1844. new_forward_ref (dbx_type)
  1845.      int dbx_type;
  1846. {
  1847.   struct forward_ref *fpnt;
  1848.   fpnt = (struct forward_ref *) malloc (sizeof (struct forward_ref));
  1849.   fpnt->next = f_ref_root;
  1850.   f_ref_root = fpnt;
  1851.   fpnt->dbx_type = dbx_type;
  1852.   fpnt->struc_numb = ++structure_count;
  1853.   fpnt->resolved = 'N';
  1854.   push (3, -1);
  1855.   total_len = 5;
  1856.   push (total_len, -2);
  1857.   struct_number = -fpnt->struc_numb;
  1858. }
  1859.  
  1860. /* this routine generates the variable descriptor used to describe non-basic
  1861.  * variables.  It calls itself recursively until it gets to the bottom of it
  1862.  * all, and then builds the descriptor backwards.  It is easiest to do it this
  1863.  *way since we must periodically write length bytes, and it is easiest if we know
  1864.  *the value when it is time to write it.
  1865.  */
  1866. static int
  1867. gen1 (spnt, array_suffix_len)
  1868.      struct VMS_DBG_Symbol *spnt;
  1869.      int array_suffix_len;
  1870. {
  1871.   struct VMS_DBG_Symbol *spnt1;
  1872.   int i;
  1873.   switch (spnt->advanced)
  1874.     {
  1875.     case VOID:
  1876.       push (DBG_S_C_VOID, -1);
  1877.       total_len += 1;
  1878.       push (total_len, -2);
  1879.       return 0;
  1880.     case BASIC:
  1881.     case FUNCTION:
  1882.       if (array_suffix_len == 0)
  1883.     {
  1884.       push (spnt->VMS_type, -1);
  1885.       push (DBG_S_C_BASIC, -1);
  1886.       total_len = 2;
  1887.       push (total_len, -2);
  1888.       return 1;
  1889.     };
  1890.       push (0, -4);
  1891.       push (0xfa02, -2);
  1892.       total_len = -2;
  1893.       return 1;
  1894.     case STRUCT:
  1895.     case UNION:
  1896.     case ENUM:
  1897.       struct_number = spnt->struc_numb;
  1898.       if (struct_number < 0)
  1899.     {
  1900.       new_forward_ref (spnt->dbx_type);
  1901.       return 1;
  1902.     }
  1903.       push (DBG_S_C_STRUCT, -1);
  1904.       total_len = 5;
  1905.       push (total_len, -2);
  1906.       return 1;
  1907.     case POINTER:
  1908.       spnt1 = find_symbol (spnt->type2);
  1909.       i = 1;
  1910.       if (spnt1 == (struct VMS_DBG_Symbol *) NULL)
  1911.     new_forward_ref (spnt->type2);
  1912.       else
  1913.     i = gen1 (spnt1, 0);
  1914.       if (i)
  1915.     {            /* (*void) is a special case, do not put pointer suffix*/
  1916.       push (DBG_S_C_POINTER, -1);
  1917.       total_len += 3;
  1918.       push (total_len, -2);
  1919.     };
  1920.       return 1;
  1921.     case ARRAY:
  1922.       spnt1 = spnt;
  1923.       while (spnt1->advanced == ARRAY)
  1924.     {
  1925.       spnt1 = find_symbol (spnt1->type2);
  1926.       if (spnt1 == (struct VMS_DBG_Symbol *) NULL)
  1927.         {
  1928.           printf ("gcc-as warning(debugger output):");
  1929.           printf ("Forward reference error, dbx type %d\n",
  1930.               spnt->type2);
  1931.           return;
  1932.         }
  1933.     };
  1934. /* It is too late to generate forward references, so the user gets a message.
  1935.  * This should only happen on a compiler error */
  1936.       i = gen1 (spnt1, 1);
  1937.       i = Apoint;
  1938.       array_suffix (spnt);
  1939.       array_suffix_len = Apoint - i;
  1940.       switch (spnt1->advanced)
  1941.     {
  1942.     case BASIC:
  1943.     case FUNCTION:
  1944.       break;
  1945.     default:
  1946.       push (0, -2);
  1947.       total_len += 2;
  1948.       push (total_len, -2);
  1949.       push (0xfa, -1);
  1950.       push (0x0101, -2);
  1951.       push (DBG_S_C_COMPLEX_ARRAY, -1);
  1952.     };
  1953.       total_len += array_suffix_len + 8;
  1954.       push (total_len, -2);
  1955.     };
  1956. }
  1957.  
  1958. /* This generates a suffix for a variable.  If it is not a defined type yet,
  1959.  * then dbx_type contains the type we are expecting so we can generate a
  1960.  * forward reference.  This calls gen1 to build most of the descriptor, and
  1961.  * then it puts the icing on at the end.  It then dumps whatever is needed
  1962.  * to get a complete descriptor (i.e. struct reference, array suffix ).
  1963.  */
  1964. static
  1965. generate_suffix (spnt, dbx_type)
  1966.      struct VMS_DBG_Symbol *spnt;
  1967.      int dbx_type;
  1968. {
  1969.   int ilen;
  1970.   int i;
  1971.   static CONST char pvoid[6] = {5, 0xaf, 0, 1, 0, 5};
  1972.   struct VMS_DBG_Symbol *spnt1;
  1973.   Apoint = 0;
  1974.   Lpnt = MAX_DEBUG_RECORD - 1;
  1975.   total_len = 0;
  1976.   struct_number = 0;
  1977.   overflow = 0;
  1978.   if (spnt == (struct VMS_DBG_Symbol *) NULL)
  1979.     new_forward_ref (dbx_type);
  1980.   else
  1981.     {
  1982.       if (spnt->VMS_type != 0xa3)
  1983.     return 0;        /* no suffix needed */
  1984.       gen1 (spnt, 0);
  1985.     };
  1986.   push (0x00af, -2);
  1987.   total_len += 4;
  1988.   push (total_len, -1);
  1989. /* if the variable descriptor overflows the record, output a descriptor for
  1990.  * a pointer to void.
  1991.  */
  1992.   if ((total_len >= MAX_DEBUG_RECORD) || overflow)
  1993.     {
  1994.       printf (" Variable descriptor %d too complicated. Defined as *void ", spnt->dbx_type);
  1995.       VMS_Store_Immediate_Data (pvoid, 6, OBJ_S_C_DBG);
  1996.       return;
  1997.     };
  1998.   i = 0;
  1999.   while (Lpnt < MAX_DEBUG_RECORD - 1)
  2000.     Local[i++] = Local[++Lpnt];
  2001.   Lpnt = i;
  2002. /* we use this for a reference to a structure that has already been defined */
  2003.   if (struct_number > 0)
  2004.     {
  2005.       VMS_Store_Immediate_Data (Local, Lpnt, OBJ_S_C_DBG);
  2006.       Lpnt = 0;
  2007.       VMS_Store_Struct (struct_number);
  2008.     };
  2009. /* we use this for a forward reference to a structure that has yet to be
  2010. *defined.  We store four bytes of zero to make room for the actual address once
  2011. * it is known
  2012. */
  2013.   if (struct_number < 0)
  2014.     {
  2015.       struct_number = -struct_number;
  2016.       VMS_Store_Immediate_Data (Local, Lpnt, OBJ_S_C_DBG);
  2017.       Lpnt = 0;
  2018.       VMS_Def_Struct (struct_number);
  2019.       for (i = 0; i < 4; i++)
  2020.     Local[Lpnt++] = 0;
  2021.       VMS_Store_Immediate_Data (Local, Lpnt, OBJ_S_C_DBG);
  2022.       Lpnt = 0;
  2023.     };
  2024.   i = 0;
  2025.   while (i < Apoint)
  2026.     Local[Lpnt++] = Asuffix[i++];
  2027.   if (Lpnt != 0)
  2028.     VMS_Store_Immediate_Data (Local, Lpnt, OBJ_S_C_DBG);
  2029.   Lpnt = 0;
  2030. }
  2031.  
  2032. /* This routine generates a symbol definition for a C sybmol for the debugger.
  2033.  * It takes a psect and offset for global symbols - if psect < 0, then this is
  2034.  * a local variable and the offset is relative to FP.  In this case it can
  2035.  * be either a variable (Offset < 0) or a parameter (Offset > 0).
  2036.  */
  2037. static
  2038. VMS_DBG_record (spnt, Psect, Offset, Name)
  2039.      struct VMS_DBG_Symbol *spnt;
  2040.      int Psect;
  2041.      int Offset;
  2042.      char *Name;
  2043. {
  2044.   char *pnt;
  2045.   char *Name_pnt;
  2046.   int j;
  2047.   int maxlen;
  2048.   int i = 0;
  2049.   Name_pnt = fix_name (Name);    /* if there are bad characters in name, convert them */
  2050.   if (Psect < 0)
  2051.     {                /* this is a local variable, referenced to SP */
  2052.       maxlen = 7 + strlen (Name_pnt);
  2053.       Local[i++] = maxlen;
  2054.       Local[i++] = spnt->VMS_type;
  2055.       if (Offset > 0)
  2056.     Local[i++] = DBG_S_C_FUNCTION_PARAMETER;
  2057.       else
  2058.     Local[i++] = DBG_S_C_LOCAL_SYM;
  2059.       COPY_LONG (&Local[i], Offset);
  2060.       i += 4;
  2061.     }
  2062.   else
  2063.     {
  2064.       maxlen = 7 + strlen (Name_pnt);    /* symbols fixed in memory */
  2065.       Local[i++] = 7 + strlen (Name_pnt);
  2066.       Local[i++] = spnt->VMS_type;
  2067.       Local[i++] = 1;
  2068.       VMS_Store_Immediate_Data (Local, i, OBJ_S_C_DBG);
  2069.       i = 0;
  2070.       VMS_Set_Data (Psect, Offset, OBJ_S_C_DBG, 0);
  2071.     }
  2072.   Local[i++] = strlen (Name_pnt);
  2073.   while (*Name_pnt != '\0')
  2074.     Local[i++] = *Name_pnt++;
  2075.   VMS_Store_Immediate_Data (Local, i, OBJ_S_C_DBG);
  2076.   if (spnt->VMS_type == DBG_S_C_ADVANCED_TYPE)
  2077.     generate_suffix (spnt, 0);
  2078. }
  2079.  
  2080.  
  2081. /* This routine parses the stabs entries in order to make the definition
  2082.  * for the debugger of local symbols and function parameters
  2083.  */
  2084. static int
  2085. VMS_local_stab_Parse (sp)
  2086.      symbolS *sp;
  2087. {
  2088.   char *pnt;
  2089.   char *pnt1;
  2090.   char *str;
  2091.   struct VMS_DBG_Symbol *spnt;
  2092.   struct VMS_Symbol *vsp;
  2093.   int dbx_type;
  2094.   int VMS_type;
  2095.   dbx_type = 0;
  2096.   str = S_GET_NAME (sp);
  2097.   pnt = (char *) strchr (str, ':');
  2098.   if (pnt == (char *) NULL)
  2099.     return;            /* no colon present */
  2100.   pnt1 = pnt++;            /* save this for later, and skip colon */
  2101.   if (*pnt == 'c')
  2102.     return 0;            /* ignore static constants */
  2103. /* there is one little catch that we must be aware of.  Sometimes function
  2104.  * parameters are optimized into registers, and the compiler, in its infiite
  2105.  * wisdom outputs stabs records for *both*.  In general we want to use the
  2106.  * register if it is present, so we must search the rest of the symbols for
  2107.  * this function to see if this parameter is assigned to a register.
  2108.  */
  2109.   {
  2110.     char *str1;
  2111.     char *pnt2;
  2112.     symbolS *sp1;
  2113.     if (*pnt == 'p')
  2114.       {
  2115.     for (sp1 = symbol_next (sp); sp1; sp1 = symbol_next (sp1))
  2116.       {
  2117.         if (!S_IS_DEBUG (sp1))
  2118.           continue;
  2119.         if (S_GET_RAW_TYPE (sp1) == N_FUN)
  2120.           {
  2121.         char * pnt3=(char*) strchr (S_GET_NAME (sp1), ':') + 1;
  2122.         if (*pnt3 == 'F' || *pnt3 == 'f') break;
  2123.           };
  2124.         if (S_GET_RAW_TYPE (sp1) != N_RSYM)
  2125.           continue;
  2126.         str1 = S_GET_NAME (sp1);    /* and get the name */
  2127.         pnt2 = str;
  2128.         while (*pnt2 != ':')
  2129.           {
  2130.         if (*pnt2 != *str1)
  2131.           break;
  2132.         pnt2++;
  2133.         str1++;
  2134.           };
  2135.         if ((*str1 != ':') || (*pnt2 != ':'))
  2136.           continue;
  2137.         return;        /* they are the same!  lets skip this one */
  2138.       };            /* for */
  2139. /* first find the dbx symbol type from list, and then find VMS type */
  2140.     pnt++;            /* skip p in case no register */
  2141.       };            /* if */
  2142.   };                /* p block */
  2143.   pnt = cvt_integer (pnt, &dbx_type);
  2144.   spnt = find_symbol (dbx_type);
  2145.   if (spnt == (struct VMS_DBG_Symbol *) NULL)
  2146.     return 0;            /*Dunno what this is*/
  2147.   *pnt1 = '\0';
  2148.   VMS_DBG_record (spnt, -1, S_GET_VALUE (sp), str);
  2149.   *pnt1 = ':';            /* and restore the string */
  2150.   return 1;
  2151. }
  2152.  
  2153. /* This routine parses a stabs entry to find the information required to define
  2154.  * a variable.  It is used for global and static variables.
  2155.  * Basically we need to know the address of the symbol.  With older versions
  2156.  * of the compiler, const symbols are
  2157.  * treated differently, in that if they are global they are written into the
  2158.  * text psect.  The global symbol entry for such a const is actually written
  2159.  * as a program entry point (Yuk!!), so if we cannot find a symbol in the list
  2160.  * of psects, we must search the entry points as well.  static consts are even
  2161.  * harder, since they are never assigned a memory address.  The compiler passes
  2162.  * a stab to tell us the value, but I am not sure what to do with it.
  2163.  */
  2164.  
  2165. static
  2166. VMS_stab_parse (sp, expected_type, type1, type2, Text_Psect)
  2167.      symbolS *sp;
  2168.      char expected_type;
  2169.      int type1, type2, Text_Psect;
  2170. {
  2171.   char *pnt;
  2172.   char *pnt1;
  2173.   char *str;
  2174.   symbolS *sp1;
  2175.   struct VMS_DBG_Symbol *spnt;
  2176.   struct VMS_Symbol *vsp;
  2177.   int dbx_type;
  2178.   int VMS_type;
  2179.   dbx_type = 0;
  2180.   str = S_GET_NAME (sp);
  2181.   pnt = (char *) strchr (str, ':');
  2182.   if (pnt == (char *) NULL)
  2183.     return;            /* no colon present */
  2184.   pnt1 = pnt;            /* save this for later*/
  2185.   pnt++;
  2186.   if (*pnt == expected_type)
  2187.     {
  2188.       pnt = cvt_integer (pnt + 1, &dbx_type);
  2189.       spnt = find_symbol (dbx_type);
  2190.       if (spnt == (struct VMS_DBG_Symbol *) NULL)
  2191.     return 0;        /*Dunno what this is*/
  2192. /* now we need to search the symbol table to find the psect and offset for
  2193.  * this variable.
  2194.  */
  2195.       *pnt1 = '\0';
  2196.       vsp = VMS_Symbols;
  2197.       while (vsp != (struct VMS_Symbol *) NULL)
  2198.     {
  2199.       pnt = S_GET_NAME (vsp->Symbol);
  2200.       if (pnt != (char *) NULL)
  2201.         if (*pnt++ == '_')
  2202. /* make sure name is the same, and make sure correct symbol type */
  2203.           if ((strlen (pnt) == strlen (str)) && (strcmp (pnt, str) == 0)
  2204.           && ((S_GET_RAW_TYPE (vsp->Symbol) == type1) ||
  2205.               (S_GET_RAW_TYPE (vsp->Symbol) == type2)))
  2206.         break;
  2207.       vsp = vsp->Next;
  2208.     };
  2209.       if (vsp != (struct VMS_Symbol *) NULL)
  2210.     {
  2211.       VMS_DBG_record (spnt, vsp->Psect_Index, vsp->Psect_Offset, str);
  2212.       *pnt1 = ':';        /* and restore the string */
  2213.       return 1;
  2214.     };
  2215. /* the symbol was not in the symbol list, but it may be an "entry point"
  2216.    if it was a constant */
  2217.       for (sp1 = symbol_rootP; sp1; sp1 = symbol_next (sp1))
  2218.     {
  2219.       /*
  2220.        *    Dispatch on STAB type
  2221.        */
  2222.       if (S_IS_DEBUG (sp1) || (S_GET_TYPE (sp1) != N_TEXT))
  2223.         continue;
  2224.       pnt = S_GET_NAME (sp1);
  2225.       if (*pnt == '_')
  2226.         pnt++;
  2227.       if (strcmp (pnt, str) == 0)
  2228.         {
  2229.           if (!gave_compiler_message && expected_type == 'G')
  2230.         {
  2231.           printf ("***Warning - the assembly code generated by the compiler has placed\n");
  2232.           printf ("global constant(s) in the text psect.  These will not be available to\n");
  2233.           printf ("other modules, since this is not the correct way to handle this. You\n");
  2234.           printf ("have two options: 1) get a patched compiler that does not put global\n");
  2235.           printf ("constants in the text psect, or 2) remove the 'const' keyword from\n");
  2236.           printf ("definitions of global variables in your source module(s).  Don't say\n");
  2237.           printf ("I didn't warn you!");
  2238.           gave_compiler_message = 1;
  2239.         };
  2240.           VMS_DBG_record (spnt,
  2241.                   Text_Psect,
  2242.                   S_GET_VALUE (sp1),
  2243.                   str);
  2244.           *pnt1 = ':';
  2245.           *S_GET_NAME (sp1) = 'L';
  2246.           /* fool assembler to not output this
  2247.            * as a routine in the TBT */
  2248.           return 1;
  2249.         };
  2250.     };
  2251.     };
  2252.   *pnt1 = ':';            /* and restore the string */
  2253.   return 0;
  2254. }
  2255.  
  2256. static
  2257. VMS_GSYM_Parse (sp, Text_Psect)
  2258.      symbolS *sp;
  2259.      int Text_Psect;
  2260. {                /* Global variables */
  2261.   VMS_stab_parse (sp, 'G', (N_UNDF | N_EXT), (N_DATA | N_EXT), Text_Psect);
  2262. }
  2263.  
  2264.  
  2265. static
  2266. VMS_LCSYM_Parse (sp, Text_Psect)
  2267.      symbolS *sp;
  2268.      int Text_Psect;
  2269. {                /* Static symbols - uninitialized */
  2270.   VMS_stab_parse (sp, 'S', N_BSS, -1, Text_Psect);
  2271. }
  2272.  
  2273. static
  2274. VMS_STSYM_Parse (sp, Text_Psect)
  2275.      symbolS *sp;
  2276.      int Text_Psect;
  2277. {                /* Static symbols - initialized */
  2278.   VMS_stab_parse (sp, 'S', N_DATA, -1, Text_Psect);
  2279. }
  2280.  
  2281.  
  2282. /* for register symbols, we must figure out what range of addresses within the
  2283.  * psect are valid. We will use the brackets in the stab directives to give us
  2284.  * guidance as to the PC range that this variable is in scope.  I am still not
  2285.  * completely comfortable with this but as I learn more, I seem to get a better
  2286.  * handle on what is going on.
  2287.  * Caveat Emptor.
  2288.  */
  2289. static
  2290. VMS_RSYM_Parse (sp, Current_Routine, Text_Psect)
  2291.      symbolS *sp, *Current_Routine;
  2292.      int Text_Psect;
  2293. {
  2294.   char *pnt;
  2295.   char *pnt1;
  2296.   char *str;
  2297.   int dbx_type;
  2298.   struct VMS_DBG_Symbol *spnt;
  2299.   int j;
  2300.   int maxlen;
  2301.   int i = 0;
  2302.   int bcnt = 0;
  2303.   int Min_Offset = -1;        /* min PC of validity */
  2304.   int Max_Offset = 0;        /* max PC of validity */
  2305.   symbolS *symbolP;
  2306.   for (symbolP = sp; symbolP; symbolP = symbol_next (symbolP))
  2307.     {
  2308.       /*
  2309.        *    Dispatch on STAB type
  2310.        */
  2311.       switch (S_GET_RAW_TYPE (symbolP))
  2312.     {
  2313.     case N_LBRAC:
  2314.       if (bcnt++ == 0)
  2315.         Min_Offset = S_GET_VALUE (symbolP);
  2316.       break;
  2317.     case N_RBRAC:
  2318.       if (--bcnt == 0)
  2319.         Max_Offset =
  2320.           S_GET_VALUE (symbolP) - 1;
  2321.       break;
  2322.     }
  2323.       if ((Min_Offset != -1) && (bcnt == 0))
  2324.     break;
  2325.       if (S_GET_RAW_TYPE (symbolP) == N_FUN)
  2326.     {
  2327.       pnt=(char*) strchr (S_GET_NAME (symbolP), ':') + 1;
  2328.       if (*pnt == 'F' || *pnt == 'f') break;
  2329.     };
  2330.     }
  2331. /* check to see that the addresses were defined.  If not, then there were no
  2332.  * brackets in the function, and we must try to search for the next function
  2333.  * Since functions can be in any order, we should search all of the symbol list
  2334.  * to find the correct ending address. */
  2335.   if (Min_Offset == -1)
  2336.     {
  2337.       int Max_Source_Offset;
  2338.       int This_Offset;
  2339.       Min_Offset = S_GET_VALUE (sp);
  2340.       for (symbolP = symbol_rootP; symbolP; symbolP = symbol_next (symbolP))
  2341.     {
  2342.       /*
  2343.        *    Dispatch on STAB type
  2344.        */
  2345.       This_Offset = S_GET_VALUE (symbolP);
  2346.       switch (S_GET_RAW_TYPE (symbolP))
  2347.         {
  2348.         case N_TEXT | N_EXT:
  2349.           if ((This_Offset > Min_Offset) && (This_Offset < Max_Offset))
  2350.         Max_Offset = This_Offset;
  2351.           break;
  2352.         case N_SLINE:
  2353.           if (This_Offset > Max_Source_Offset)
  2354.         Max_Source_Offset = This_Offset;
  2355.         }
  2356.     }
  2357. /* if this is the last routine, then we use the PC of the last source line
  2358.  * as a marker of the max PC for which this reg is valid */
  2359.       if (Max_Offset == 0x7fffffff)
  2360.     Max_Offset = Max_Source_Offset;
  2361.     };
  2362.   dbx_type = 0;
  2363.   str = S_GET_NAME (sp);
  2364.   pnt = (char *) strchr (str, ':');
  2365.   if (pnt == (char *) NULL)
  2366.     return;            /* no colon present */
  2367.   pnt1 = pnt;            /* save this for later*/
  2368.   pnt++;
  2369.   if (*pnt != 'r')
  2370.     return 0;
  2371.   pnt = cvt_integer (pnt + 1, &dbx_type);
  2372.   spnt = find_symbol (dbx_type);
  2373.   if (spnt == (struct VMS_DBG_Symbol *) NULL)
  2374.     return 0;            /*Dunno what this is yet*/
  2375.   *pnt1 = '\0';
  2376.   pnt = fix_name (S_GET_NAME (sp));    /* if there are bad characters in name, convert them */
  2377.   maxlen = 25 + strlen (pnt);
  2378.   Local[i++] = maxlen;
  2379.   Local[i++] = spnt->VMS_type;
  2380.   Local[i++] = 0xfb;
  2381.   Local[i++] = strlen (pnt) + 1;
  2382.   Local[i++] = 0x00;
  2383.   Local[i++] = 0x00;
  2384.   Local[i++] = 0x00;
  2385.   Local[i++] = strlen (pnt);
  2386.   while (*pnt != '\0')
  2387.     Local[i++] = *pnt++;
  2388.   Local[i++] = 0xfd;
  2389.   Local[i++] = 0x0f;
  2390.   Local[i++] = 0x00;
  2391.   Local[i++] = 0x03;
  2392.   Local[i++] = 0x01;
  2393.   VMS_Store_Immediate_Data (Local, i, OBJ_S_C_DBG);
  2394.   i = 0;
  2395.   VMS_Set_Data (Text_Psect, Min_Offset, OBJ_S_C_DBG, 1);
  2396.   VMS_Set_Data (Text_Psect, Max_Offset, OBJ_S_C_DBG, 1);
  2397.   Local[i++] = 0x03;
  2398.   Local[i++] = S_GET_VALUE (sp);
  2399.   Local[i++] = 0x00;
  2400.   Local[i++] = 0x00;
  2401.   Local[i++] = 0x00;
  2402.   VMS_Store_Immediate_Data (Local, i, OBJ_S_C_DBG);
  2403.   *pnt1 = ':';
  2404.   if (spnt->VMS_type == DBG_S_C_ADVANCED_TYPE)
  2405.     generate_suffix (spnt, 0);
  2406. }
  2407.  
  2408. /* this function examines a structure definition, checking all of the elements
  2409.  * to make sure that all of them are fully defined.  The only thing that we
  2410.  * kick out are arrays of undefined structs, since we do not know how big
  2411.  * they are.  All others we can handle with a normal forward reference.
  2412.  */
  2413. static int
  2414. forward_reference (pnt)
  2415.      char *pnt;
  2416. {
  2417.   int i;
  2418.   struct VMS_DBG_Symbol *spnt;
  2419.   struct VMS_DBG_Symbol *spnt1;
  2420.   pnt = cvt_integer (pnt + 1, &i);
  2421.   if (*pnt == ';')
  2422.     return 0;            /* no forward references */
  2423.   do
  2424.     {
  2425.       pnt = (char *) strchr (pnt, ':');
  2426.       pnt = cvt_integer (pnt + 1, &i);
  2427.       spnt = find_symbol (i);
  2428.       if(spnt != (struct VMS_DBG_Symbol*) NULL) {
  2429.     while((spnt->advanced == POINTER) || (spnt->advanced == ARRAY))
  2430.     {
  2431.       i = spnt->type2;
  2432.       spnt1 = find_symbol (spnt->type2);
  2433.       if ((spnt->advanced == ARRAY) &&
  2434.           (spnt1 == (struct VMS_DBG_Symbol *) NULL))
  2435.         return 1;
  2436.       if (spnt1 == (struct VMS_DBG_Symbol *) NULL)
  2437.         break;
  2438.       spnt = spnt1;
  2439.     };
  2440.       };
  2441.       pnt = cvt_integer (pnt + 1, &i);
  2442.       pnt = cvt_integer (pnt + 1, &i);
  2443.   } while (*++pnt != ';');
  2444.   return 0;            /* no forward refences found */
  2445. }
  2446.  
  2447. /* Used to check a single element of a structure on the final pass*/
  2448.  
  2449. static int
  2450. final_forward_reference (spnt)
  2451.   struct VMS_DBG_Symbol * spnt;
  2452. {
  2453.     struct VMS_DBG_Symbol * spnt1;
  2454.     if(spnt != (struct VMS_DBG_Symbol*) NULL) {
  2455.       while((spnt->advanced == POINTER) || (spnt->advanced == ARRAY)){
  2456.         spnt1 = find_symbol(spnt->type2);
  2457.         if((spnt->advanced == ARRAY) &&
  2458.            (spnt1 == (struct VMS_DBG_Symbol*) NULL))return 1;
  2459.         if(spnt1 == (struct VMS_DBG_Symbol*) NULL) break;
  2460.         spnt=spnt1;
  2461.       };
  2462.     };
  2463.     return 0;    /* no forward refences found */
  2464. }
  2465.  
  2466. /* This routine parses the stabs directives to find any definitions of dbx type
  2467.  * numbers.  It makes a note of all of them, creating a structure element
  2468.  * of VMS_DBG_Symbol that describes it.  This also generates the info for the
  2469.  * debugger that describes the struct/union/enum, so that further references
  2470.  * to these data types will be by number
  2471.  *     We have to process pointers right away, since there can be references
  2472.  * to them later in the same stabs directive.  We cannot have forward
  2473.  * references to pointers, (but we can have a forward reference to a pointer to
  2474.  * a structure/enum/union) and this is why we process them immediately.
  2475.  * After we process the pointer, then we search for defs that are nested even
  2476.  * deeper.
  2477.  * 8/15/92: We have to process arrays right away too, because there can
  2478.  * be multiple references to identical array types in one structure
  2479.  * definition, and only the first one has the definition.  (We tend to
  2480.  * parse from the back going forward.
  2481.  */
  2482. static int
  2483. VMS_typedef_parse (str)
  2484.      char *str;
  2485. {
  2486.   char *pnt;
  2487.   char *pnt1;
  2488.   char *pnt2;
  2489.   int i;
  2490.   int dtype;
  2491.   struct forward_ref *fpnt;
  2492.   int i1, i2, i3;
  2493.   int convert_integer;
  2494.   struct VMS_DBG_Symbol *spnt;
  2495.   struct VMS_DBG_Symbol *spnt1;
  2496. /* check for any nested def's */
  2497.   pnt = (char *) strchr (str + 1, '=');
  2498.   if ((pnt != (char *) NULL) && (*(str + 1) != '*')
  2499.     && (str[1] != 'a' || str[2] != 'r'))
  2500.     if (VMS_typedef_parse (pnt) == 1)
  2501.       return 1;
  2502. /* now find dbx_type of entry */
  2503.   pnt = str - 1;
  2504.   if (*pnt == 'c')
  2505.     {                /* check for static constants */
  2506.       *str = '\0';        /* for now we ignore them */
  2507.       return 0;
  2508.     };
  2509.   while ((*pnt <= '9') && (*pnt >= '0'))
  2510.     pnt--;
  2511.   pnt++;            /* and get back to the number */
  2512.   cvt_integer (pnt, &i1);
  2513.   spnt = find_symbol (i1);
  2514. /* first we see if this has been defined already, due to a forward reference*/
  2515.   if (spnt == (struct VMS_DBG_Symbol *) NULL)
  2516.     {
  2517.       if (VMS_Symbol_type_list == (struct VMS_DBG_Symbol *) NULL)
  2518.     {
  2519.       spnt = (struct VMS_DBG_Symbol *) malloc (sizeof (struct VMS_DBG_Symbol));
  2520.       spnt->next = (struct VMS_DBG_Symbol *) NULL;
  2521.       VMS_Symbol_type_list = spnt;
  2522.     }
  2523.       else
  2524.     {
  2525.       spnt = (struct VMS_DBG_Symbol *) malloc (sizeof (struct VMS_DBG_Symbol));
  2526.       spnt->next = VMS_Symbol_type_list;
  2527.       VMS_Symbol_type_list = spnt;
  2528.     };
  2529.       spnt->dbx_type = i1;    /* and save the type */
  2530.     };
  2531. /* for structs and unions, do a partial parse, otherwise we sometimes get
  2532.  * circular definitions that are impossible to resolve. We read enough info
  2533.  * so that any reference to this type has enough info to be resolved
  2534.  */
  2535.   pnt = str + 1;        /* point to character past equal sign */
  2536.   if ((*pnt == 'u') || (*pnt == 's'))
  2537.     {
  2538.     };
  2539.   if ((*pnt <= '9') && (*pnt >= '0'))
  2540.     {
  2541.       if (type_check ("void"))
  2542.     {            /* this is the void symbol */
  2543.       *str = '\0';
  2544.       spnt->advanced = VOID;
  2545.       return 0;
  2546.     };
  2547.       if (type_check ("unknown type"))
  2548.     {            /* this is the void symbol */
  2549.       *str = '\0';
  2550.       spnt->advanced = UNKNOWN;
  2551.       return 0;
  2552.     };
  2553.       pnt1 = cvt_integer(pnt,&i1);
  2554.       if(i1 != spnt->dbx_type)
  2555.     {
  2556.       spnt->advanced = ALIAS;
  2557.       spnt->type2 = i1;
  2558.       strcpy(str, pnt1);
  2559.       return 0;
  2560.     }
  2561.       printf ("gcc-as warning(debugger output):");
  2562.       printf (" %d is an unknown untyped variable.\n", spnt->dbx_type);
  2563.       return 1;            /* do not know what this is */
  2564.     };
  2565. /* now define this module*/
  2566.   pnt = str + 1;        /* point to character past equal sign */
  2567.   switch (*pnt)
  2568.     {
  2569.     case 'r':
  2570.       spnt->advanced = BASIC;
  2571.       if (type_check ("int"))
  2572.     {
  2573.       spnt->VMS_type = DBG_S_C_SLINT;
  2574.       spnt->data_size = 4;
  2575.     }
  2576.       else if (type_check ("long int"))
  2577.     {
  2578.       spnt->VMS_type = DBG_S_C_SLINT;
  2579.       spnt->data_size = 4;
  2580.     }
  2581.       else if (type_check ("unsigned int"))
  2582.     {
  2583.       spnt->VMS_type = DBG_S_C_ULINT;
  2584.       spnt->data_size = 4;
  2585.     }
  2586.       else if (type_check ("long unsigned int"))
  2587.     {
  2588.       spnt->VMS_type = DBG_S_C_ULINT;
  2589.       spnt->data_size = 4;
  2590.     }
  2591.       else if (type_check ("short int"))
  2592.     {
  2593.       spnt->VMS_type = DBG_S_C_SSINT;
  2594.       spnt->data_size = 2;
  2595.     }
  2596.       else if (type_check ("short unsigned int"))
  2597.     {
  2598.       spnt->VMS_type = DBG_S_C_USINT;
  2599.       spnt->data_size = 2;
  2600.     }
  2601.       else if (type_check ("char"))
  2602.     {
  2603.       spnt->VMS_type = DBG_S_C_SCHAR;
  2604.       spnt->data_size = 1;
  2605.     }
  2606.       else if (type_check ("signed char"))
  2607.     {
  2608.       spnt->VMS_type = DBG_S_C_SCHAR;
  2609.       spnt->data_size = 1;
  2610.     }
  2611.       else if (type_check ("unsigned char"))
  2612.     {
  2613.       spnt->VMS_type = DBG_S_C_UCHAR;
  2614.       spnt->data_size = 1;
  2615.     }
  2616.       else if (type_check ("float"))
  2617.     {
  2618.       spnt->VMS_type = DBG_S_C_REAL4;
  2619.       spnt->data_size = 4;
  2620.     }
  2621.       else if (type_check ("double"))
  2622.     {
  2623.       spnt->VMS_type = DBG_S_C_REAL8;
  2624.       spnt->data_size = 8;
  2625.     }
  2626.       pnt1 = (char *) strchr (str, ';') + 1;
  2627.       break;
  2628.     case 's':
  2629.     case 'u':
  2630.       if (*pnt == 's')
  2631.     spnt->advanced = STRUCT;
  2632.       else
  2633.     spnt->advanced = UNION;
  2634.       spnt->VMS_type = DBG_S_C_ADVANCED_TYPE;
  2635.       pnt1 = cvt_integer (pnt + 1, &spnt->data_size);
  2636.       if (!final_pass && forward_reference(pnt))
  2637.     {
  2638.       spnt->struc_numb = -1;
  2639.       return 1;
  2640.     }
  2641.       spnt->struc_numb = ++structure_count;
  2642.       pnt1--;
  2643.       pnt = get_struct_name (str);
  2644.       VMS_Def_Struct (spnt->struc_numb);
  2645.       fpnt = f_ref_root;
  2646.       while (fpnt != (struct forward_ref *) NULL)
  2647.     {
  2648.       if (fpnt->dbx_type == spnt->dbx_type)
  2649.         {
  2650.           fpnt->resolved = 'Y';
  2651.           VMS_Set_Struct (fpnt->struc_numb);
  2652.           VMS_Store_Struct (spnt->struc_numb);
  2653.         };
  2654.       fpnt = fpnt->next;
  2655.     };
  2656.       VMS_Set_Struct (spnt->struc_numb);
  2657.       i = 0;
  2658.       Local[i++] = 11 + strlen (pnt);
  2659.       Local[i++] = DBG_S_C_STRUCT_START;
  2660.       Local[i++] = 0x80;
  2661.       for (i1 = 0; i1 < 4; i1++)
  2662.     Local[i++] = 0x00;
  2663.       Local[i++] = strlen (pnt);
  2664.       pnt2 = pnt;
  2665.       while (*pnt2 != '\0')
  2666.     Local[i++] = *pnt2++;
  2667.       i2 = spnt->data_size * 8;    /* number of bits */
  2668.       COPY_LONG(&Local[i], i2);
  2669.       i += 4;
  2670.       VMS_Store_Immediate_Data (Local, i, OBJ_S_C_DBG);
  2671.       i = 0;
  2672.       if (pnt != symbol_name)
  2673.     {
  2674.       pnt += strlen (pnt);
  2675.       *pnt = ':';
  2676.     };            /* replace colon for later */
  2677.       while (*++pnt1 != ';')
  2678.     {
  2679.       pnt = (char *) strchr (pnt1, ':');
  2680.       *pnt = '\0';
  2681.       pnt2 = pnt1;
  2682.       pnt1 = cvt_integer (pnt + 1, &dtype);
  2683.       pnt1 = cvt_integer (pnt1 + 1, &i2);
  2684.       pnt1 = cvt_integer (pnt1 + 1, &i3);
  2685.       if ((dtype == 1) && (i3 != 32))
  2686.         {            /* bitfield */
  2687.           Apoint = 0;
  2688.           push (19 + strlen (pnt2), 1);
  2689.           push (0xfa22, 2);
  2690.           push (1 + strlen (pnt2), 4);
  2691.           push (strlen (pnt2), 1);
  2692.           while (*pnt2 != '\0')
  2693.         push (*pnt2++, 1);
  2694.           push (i3, 2);    /* size of bitfield */
  2695.           push (0x0d22, 2);
  2696.           push (0x00, 4);
  2697.           push (i2, 4);    /* start position */
  2698.           VMS_Store_Immediate_Data (Asuffix, Apoint, OBJ_S_C_DBG);
  2699.           Apoint = 0;
  2700.         }
  2701.       else
  2702.         {
  2703.           Local[i++] = 7 + strlen (pnt2);
  2704.           spnt1 = find_symbol (dtype);
  2705.           /* check if this is a forward reference */
  2706.           if(final_pass && final_forward_reference(spnt1))
  2707.         {
  2708.           printf("gcc-as warning(debugger output):");
  2709.           printf("structure element %s has undefined type\n",pnt2);
  2710.           i--;
  2711.           continue;
  2712.         }
  2713.           if (spnt1 != (struct VMS_DBG_Symbol *) NULL)
  2714.         Local[i++] = spnt1->VMS_type;
  2715.           else
  2716.         Local[i++] = DBG_S_C_ADVANCED_TYPE;
  2717.           Local[i++] = DBG_S_C_STRUCT_ITEM;
  2718.           COPY_LONG (&Local[i], i2);
  2719.           i += 4;
  2720.           Local[i++] = strlen (pnt2);
  2721.           while (*pnt2 != '\0')
  2722.         Local[i++] = *pnt2++;
  2723.           VMS_Store_Immediate_Data (Local, i, OBJ_S_C_DBG);
  2724.           i = 0;
  2725.           if (spnt1 == (struct VMS_DBG_Symbol *) NULL)
  2726.         generate_suffix (spnt1, dtype);
  2727.           else if (spnt1->VMS_type == DBG_S_C_ADVANCED_TYPE)
  2728.         generate_suffix (spnt1, 0);
  2729.         };
  2730.     };
  2731.       pnt1++;
  2732.       Local[i++] = 0x01;    /* length byte */
  2733.       Local[i++] = DBG_S_C_STRUCT_END;
  2734.       VMS_Store_Immediate_Data (Local, i, OBJ_S_C_DBG);
  2735.       i = 0;
  2736.       break;
  2737.     case 'e':
  2738.       spnt->advanced = ENUM;
  2739.       spnt->VMS_type = DBG_S_C_ADVANCED_TYPE;
  2740.       spnt->struc_numb = ++structure_count;
  2741.       spnt->data_size = 4;
  2742.       VMS_Def_Struct (spnt->struc_numb);
  2743.       fpnt = f_ref_root;
  2744.       while (fpnt != (struct forward_ref *) NULL)
  2745.     {
  2746.       if (fpnt->dbx_type == spnt->dbx_type)
  2747.         {
  2748.           fpnt->resolved = 'Y';
  2749.           VMS_Set_Struct (fpnt->struc_numb);
  2750.           VMS_Store_Struct (spnt->struc_numb);
  2751.         };
  2752.       fpnt = fpnt->next;
  2753.     };
  2754.       VMS_Set_Struct (spnt->struc_numb);
  2755.       i = 0;
  2756.       Local[i++] = 3 + strlen (symbol_name);
  2757.       Local[i++] = DBG_S_C_ENUM_START;
  2758.       Local[i++] = 0x20;
  2759.       Local[i++] = strlen (symbol_name);
  2760.       pnt2 = symbol_name;
  2761.       while (*pnt2 != '\0')
  2762.     Local[i++] = *pnt2++;
  2763.       VMS_Store_Immediate_Data (Local, i, OBJ_S_C_DBG);
  2764.       i = 0;
  2765.       while (*++pnt != ';')
  2766.     {
  2767.       pnt1 = (char *) strchr (pnt, ':');
  2768.       *pnt1++ = '\0';
  2769.       pnt1 = cvt_integer (pnt1, &i1);
  2770.       Local[i++] = 7 + strlen (pnt);
  2771.       Local[i++] = DBG_S_C_ENUM_ITEM;
  2772.       Local[i++] = 0x00;
  2773.       COPY_LONG (&Local[i], i1);
  2774.       i += 4;
  2775.       Local[i++] = strlen (pnt);
  2776.       pnt2 = pnt;
  2777.       while (*pnt != '\0')
  2778.         Local[i++] = *pnt++;
  2779.       VMS_Store_Immediate_Data (Local, i, OBJ_S_C_DBG);
  2780.       i = 0;
  2781.       pnt = pnt1;        /* Skip final semicolon */
  2782.     };
  2783.       Local[i++] = 0x01;    /* len byte */
  2784.       Local[i++] = DBG_S_C_ENUM_END;
  2785.       VMS_Store_Immediate_Data (Local, i, OBJ_S_C_DBG);
  2786.       i = 0;
  2787.       pnt1 = pnt + 1;
  2788.       break;
  2789.     case 'a':
  2790.       spnt->advanced = ARRAY;
  2791.       spnt->VMS_type = DBG_S_C_ADVANCED_TYPE;
  2792.       pnt = (char *) strchr (pnt, ';');
  2793.       if (pnt == (char *) NULL)
  2794.     return 1;
  2795.       pnt1 = cvt_integer (pnt + 1, &spnt->index_min);
  2796.       pnt1 = cvt_integer (pnt1 + 1, &spnt->index_max);
  2797.       pnt1 = cvt_integer (pnt1 + 1, &spnt->type2);
  2798.       pnt=(char*)strchr(str+1,'=');
  2799.       if((pnt != (char*) NULL)) 
  2800.     if(VMS_typedef_parse(pnt) == 1 ) return 1;
  2801.       break;
  2802.     case 'f':
  2803.       spnt->advanced = FUNCTION;
  2804.       spnt->VMS_type = DBG_S_C_FUNCTION_ADDR;
  2805.       /* this masquerades as a basic type*/
  2806.       spnt->data_size = 4;
  2807.       pnt1 = cvt_integer (pnt + 1, &spnt->type2);
  2808.       break;
  2809.     case '*':
  2810.       spnt->advanced = POINTER;
  2811.       spnt->VMS_type = DBG_S_C_ADVANCED_TYPE;
  2812.       spnt->data_size = 4;
  2813.       pnt1 = cvt_integer (pnt + 1, &spnt->type2);
  2814.       pnt = (char *) strchr (str + 1, '=');
  2815.       if ((pnt != (char *) NULL))
  2816.     if (VMS_typedef_parse (pnt) == 1)
  2817.       return 1;
  2818.       break;
  2819.     default:
  2820.       spnt->advanced = UNKNOWN;
  2821.       spnt->VMS_type = 0;
  2822.       printf ("gcc-as warning(debugger output):");
  2823.       printf (" %d is an unknown type of variable.\n", spnt->dbx_type);
  2824.       return 1;            /* unable to decipher */
  2825.     };
  2826. /* this removes the evidence of the definition so that the outer levels of
  2827. parsing do not have to worry about it */
  2828.   pnt = str;
  2829.   while (*pnt1 != '\0')
  2830.     *pnt++ = *pnt1++;
  2831.   *pnt = '\0';
  2832.   return 0;
  2833. }
  2834.  
  2835.  
  2836. /*
  2837.  * This is the root routine that parses the stabs entries for definitions.
  2838.  * it calls VMS_typedef_parse, which can in turn call itself.
  2839.  * We need to be careful, since sometimes there are forward references to
  2840.  * other symbol types, and these cannot be resolved until we have completed
  2841.  * the parse.
  2842.  *
  2843.  * Also check and see if we are using continuation stabs, if we are, then
  2844.  * paste together the entire contents of the stab before we pass it to 
  2845.  * VMS_typedef_parse.
  2846.  */
  2847. static int
  2848. VMS_LSYM_Parse ()
  2849. {
  2850.   char *pnt;
  2851.   char *pnt1;
  2852.   char *pnt2;
  2853.   char *str;
  2854.   char *parse_buffer = 0;
  2855.   char fixit[10];
  2856.   int incomplete, i, pass, incom1;
  2857.   struct VMS_DBG_Symbol *spnt;
  2858.   struct VMS_Symbol *vsp;
  2859.   struct forward_ref *fpnt;
  2860.   symbolS *sp;
  2861.   pass = 0;
  2862.   final_pass = 0;
  2863.   incomplete = 0;
  2864.   do
  2865.     {
  2866.       incom1 = incomplete;
  2867.       incomplete = 0;
  2868.       for (sp = symbol_rootP; sp; sp = symbol_next (sp))
  2869.     {
  2870.       /*
  2871.        *    Deal with STAB symbols
  2872.        */
  2873.       if (S_IS_DEBUG (sp))
  2874.         {
  2875.           /*
  2876.            *    Dispatch on STAB type
  2877.            */
  2878.           switch (S_GET_RAW_TYPE (sp))
  2879.         {
  2880.         case N_GSYM:
  2881.         case N_LCSYM:
  2882.         case N_STSYM:
  2883.         case N_PSYM:
  2884.         case N_RSYM:
  2885.         case N_LSYM:
  2886.         case N_FUN:    /*sometimes these contain typedefs*/
  2887.           str = S_GET_NAME (sp);
  2888.           symbol_name = str;
  2889.           pnt = str + strlen(str) -1;
  2890.           if (*pnt == '?')  /* Continuation stab.  */
  2891.             {
  2892.               symbolS *spnext;
  2893.               int tlen = 0;
  2894.               spnext = sp;
  2895.               do {
  2896.             tlen += strlen(str) - 1;
  2897.             spnext = symbol_next (spnext);
  2898.             str = S_GET_NAME (spnext);
  2899.             pnt = str + strlen(str) - 1;
  2900.               } while (*pnt == '?');
  2901.               tlen += strlen(str);
  2902.               parse_buffer = (char *) malloc (tlen + 1);
  2903.               strcpy(parse_buffer, S_GET_NAME (sp));
  2904.               pnt2 = parse_buffer + strlen(S_GET_NAME (sp)) - 1;
  2905.               *pnt2 = '\0';
  2906.               spnext = sp;
  2907.               do {
  2908.             spnext = symbol_next (spnext);
  2909.             str = S_GET_NAME (spnext);
  2910.             strcat (pnt2, S_GET_NAME (spnext));
  2911.             pnt2 +=  strlen(str) - 1;
  2912.             *str = '\0';  /* Erase this string  */
  2913.             if (*pnt2 != '?') break;
  2914.             *pnt2 = '\0';
  2915.               } while (1 == 1);
  2916.               str = parse_buffer;
  2917.               symbol_name = str;
  2918.             };
  2919.           pnt = (char *) strchr (str, ':');
  2920.           if (pnt != (char *) NULL)
  2921.             {
  2922.               *pnt = '\0';
  2923.               pnt1 = pnt + 1;
  2924.               pnt2 = (char *) strchr (pnt1, '=');
  2925.               if (pnt2 != (char *) NULL)
  2926.             incomplete += VMS_typedef_parse (pnt2);
  2927.               if (parse_buffer){
  2928.             /*  At this point the parse buffer should just contain name:nn.
  2929.                 If it does not, then we are in real trouble. Anyway, 
  2930.                 this is always shorter than the original line. */
  2931.             strcpy(S_GET_NAME (sp), parse_buffer);
  2932.             free (parse_buffer);
  2933.             parse_buffer = 0;
  2934.               };
  2935.               *pnt = ':';    /* put back colon so variable def code finds dbx_type*/
  2936.             };
  2937.           break;
  2938.         }        /*switch*/
  2939.         }            /* if */
  2940.     }            /*for*/
  2941.       pass++;
  2942. /* Make one last pass, if needed, and define whatever we can that is left */
  2943.       if(final_pass == 0 && incomplete == incom1)
  2944.         {
  2945.           final_pass = 1;
  2946.       incom1 ++;  /* Force one last pass through */
  2947.     };
  2948.   } while ((incomplete != 0) && (incomplete != incom1));
  2949.   /* repeat until all refs resolved if possible */
  2950. /*    if (pass > 1) printf(" Required %d passes\n",pass);*/
  2951.   if (incomplete != 0)
  2952.     {
  2953.       printf ("gcc-as warning(debugger output):");
  2954.       printf ("Unable to resolve %d circular references.\n", incomplete);
  2955.     };
  2956.   fpnt = f_ref_root;
  2957.   symbol_name = "\0";
  2958.   while (fpnt != (struct forward_ref *) NULL)
  2959.     {
  2960.       if (fpnt->resolved != 'Y')
  2961.     {
  2962.       if (find_symbol (fpnt->dbx_type) !=
  2963.           (struct VMS_DBG_Symbol *) NULL)
  2964.         {
  2965.           printf ("gcc-as warning(debugger output):");
  2966.           printf ("Forward reference error, dbx type %d\n",
  2967.               fpnt->dbx_type);
  2968.           break;
  2969.         };
  2970.       fixit[0] = 0;
  2971.       sprintf (&fixit[1], "%d=s4;", fpnt->dbx_type);
  2972.       pnt2 = (char *) strchr (&fixit[1], '=');
  2973.       VMS_typedef_parse (pnt2);
  2974.     };
  2975.       fpnt = fpnt->next;
  2976.     };
  2977. }
  2978.  
  2979. static
  2980. Define_Local_Symbols (s1, s2)
  2981.      symbolS *s1, *s2;
  2982. {
  2983.   symbolS *symbolP1;
  2984.   for (symbolP1 = symbol_next (s1); symbolP1 != s2; symbolP1 = symbol_next (symbolP1))
  2985.     {
  2986.       if (symbolP1 == (symbolS *) NULL)
  2987.     return;
  2988.       if (S_GET_RAW_TYPE (symbolP1) == N_FUN)
  2989.     {
  2990.       char * pnt=(char*) strchr (S_GET_NAME (symbolP1), ':') + 1;
  2991.       if (*pnt == 'F' || *pnt == 'f') break;
  2992.     };
  2993.       /*
  2994.        *    Deal with STAB symbols
  2995.        */
  2996.       if (S_IS_DEBUG (symbolP1))
  2997.     {
  2998.       /*
  2999.        *    Dispatch on STAB type
  3000.        */
  3001.       switch (S_GET_RAW_TYPE (symbolP1))
  3002.         {
  3003.         case N_LSYM:
  3004.         case N_PSYM:
  3005.           VMS_local_stab_Parse (symbolP1);
  3006.           break;
  3007.         case N_RSYM:
  3008.           VMS_RSYM_Parse (symbolP1, Current_Routine, Text_Psect);
  3009.           break;
  3010.         }            /*switch*/
  3011.     }            /* if */
  3012.     }                /* for */
  3013. }
  3014.  
  3015.  
  3016. /* This function crawls the symbol chain searching for local symbols that need
  3017.  * to be described to the debugger.  When we enter a new scope with a "{", it
  3018.  * creates a new "block", which helps the debugger keep track of which scope
  3019.  * we are currently in.
  3020.  */
  3021.  
  3022. static symbolS *
  3023. Define_Routine (symbolP, Level)
  3024.      symbolS *symbolP;
  3025.      int Level;
  3026. {
  3027.   symbolS *sstart;
  3028.   symbolS *symbolP1;
  3029.   char str[10];
  3030.   int rcount = 0;
  3031.   int Offset;
  3032.   sstart = symbolP;
  3033.   for (symbolP1 = symbol_next (symbolP); symbolP1; symbolP1 = symbol_next (symbolP1))
  3034.     {
  3035.       if (S_GET_RAW_TYPE (symbolP1) == N_FUN)
  3036.     {
  3037.       char * pnt=(char*) strchr (S_GET_NAME (symbolP1), ':') + 1;
  3038.       if (*pnt == 'F' || *pnt == 'f') break;
  3039.     };
  3040.       /*
  3041.        *    Deal with STAB symbols
  3042.        */
  3043.       if (S_IS_DEBUG (symbolP1))
  3044.     {
  3045.       /*
  3046.        *    Dispatch on STAB type
  3047.        */
  3048.       switch (S_GET_RAW_TYPE (symbolP1))
  3049.         {
  3050.         case N_LBRAC:
  3051.           if (Level != 0)
  3052.         {
  3053.           sprintf (str, "$%d", rcount++);
  3054.           VMS_TBT_Block_Begin (symbolP1, Text_Psect, str);
  3055.         };
  3056.           Offset = S_GET_VALUE (symbolP1);
  3057.           Define_Local_Symbols (sstart, symbolP1);
  3058.           symbolP1 =
  3059.         Define_Routine (symbolP1, Level + 1);
  3060.           if (Level != 0)
  3061.         VMS_TBT_Block_End (S_GET_VALUE (symbolP1) -
  3062.                    Offset);
  3063.           sstart = symbolP1;
  3064.           break;
  3065.         case N_RBRAC:
  3066.           return symbolP1;
  3067.         }            /*switch*/
  3068.     }            /* if */
  3069.     }                /* for */
  3070.   /* we end up here if there were no brackets in this function. Define
  3071. everything */
  3072.   Define_Local_Symbols (sstart, (symbolS *) 0);
  3073.   return symbolP1;
  3074. }
  3075.  
  3076.  
  3077. static
  3078. VMS_DBG_Define_Routine (symbolP, Curr_Routine, Txt_Psect)
  3079.      symbolS *symbolP;
  3080.      symbolS *Curr_Routine;
  3081.      int Txt_Psect;
  3082. {
  3083.   Current_Routine = Curr_Routine;
  3084.   Text_Psect = Txt_Psect;
  3085.   Define_Routine (symbolP, 0);
  3086. }
  3087.  
  3088.  
  3089.  
  3090.  
  3091. #ifndef HO_VMS
  3092. #include <sys/types.h>
  3093. #include <time.h>
  3094.  
  3095. /* Manufacure a VMS like time on a unix based system. */
  3096. get_VMS_time_on_unix (Now)
  3097.      char *Now;
  3098. {
  3099.   char *pnt;
  3100.   time_t timeb;
  3101.   time (&timeb);
  3102.   pnt = ctime (&timeb);
  3103.   pnt[3] = 0;
  3104.   pnt[7] = 0;
  3105.   pnt[10] = 0;
  3106.   pnt[16] = 0;
  3107.   pnt[24] = 0;
  3108.   sprintf (Now, "%2s-%3s-%s %s", pnt + 8, pnt + 4, pnt + 20, pnt + 11);
  3109. }
  3110.  
  3111. #endif /* not HO_VMS */
  3112. /*
  3113.  *    Write the MHD (Module Header) records
  3114.  */
  3115. static
  3116. Write_VMS_MHD_Records ()
  3117. {
  3118.   register char *cp, *cp1;
  3119.   register int i;
  3120.   struct
  3121.   {
  3122.     int Size;
  3123.     char *Ptr;
  3124.   } Descriptor;
  3125.   char Module_Name[256];
  3126.   char Now[18];
  3127.  
  3128.   /*
  3129.    *    We are writing a module header record
  3130.    */
  3131.   Set_VMS_Object_File_Record (OBJ_S_C_HDR);
  3132.   /*
  3133.    *    ***************************
  3134.    *    *MAIN MODULE HEADER RECORD*
  3135.    *    ***************************
  3136.    *
  3137.    *    Store record type and header type
  3138.    */
  3139.   PUT_CHAR (OBJ_S_C_HDR);
  3140.   PUT_CHAR (MHD_S_C_MHD);
  3141.   /*
  3142.    *    Structure level is 0
  3143.    */
  3144.   PUT_CHAR (OBJ_S_C_STRLVL);
  3145.   /*
  3146.    *    Maximum record size is size of the object record buffer
  3147.    */
  3148.   PUT_SHORT (sizeof (Object_Record_Buffer));
  3149.   /*
  3150.    *    Get module name (the FILENAME part of the object file)
  3151.    */
  3152.   cp = out_file_name;
  3153.   cp1 = Module_Name;
  3154.   while (*cp)
  3155.     {
  3156.       if ((*cp == ']') || (*cp == '>') ||
  3157.       (*cp == ':') || (*cp == '/'))
  3158.     {
  3159.       cp1 = Module_Name;
  3160.       cp++;
  3161.       continue;
  3162.     }
  3163.       *cp1++ = islower (*cp) ? toupper (*cp++) : *cp++;
  3164.     }
  3165.   *cp1 = 0;
  3166.   /*
  3167.    *    Limit it to 31 characters and store in the object record
  3168.    */
  3169.   while (--cp1 >= Module_Name)
  3170.     if (*cp1 == '.')
  3171.       *cp1 = 0;
  3172.   if (strlen (Module_Name) > 31)
  3173.     {
  3174.       if (flagseen['+'])
  3175.     printf ("%s: Module name truncated: %s\n", myname, Module_Name);
  3176.       Module_Name[31] = 0;
  3177.     }
  3178.   PUT_COUNTED_STRING (Module_Name);
  3179.   /*
  3180.    *    Module Version is "V1.0"
  3181.    */
  3182.   PUT_COUNTED_STRING ("V1.0");
  3183.   /*
  3184.    *    Creation time is "now" (17 chars of time string)
  3185.    */
  3186. #ifndef HO_VMS
  3187.   get_VMS_time_on_unix (&Now[0]);
  3188. #else /* HO_VMS */
  3189.   Descriptor.Size = 17;
  3190.   Descriptor.Ptr = Now;
  3191.   sys$asctim (0, &Descriptor, 0, 0);
  3192. #endif /* HO_VMS */
  3193.   for (i = 0; i < 17; i++)
  3194.     PUT_CHAR (Now[i]);
  3195.   /*
  3196.    *    Patch time is "never" (17 zeros)
  3197.    */
  3198.   for (i = 0; i < 17; i++)
  3199.     PUT_CHAR (0);
  3200.   /*
  3201.    *    Flush the record
  3202.    */
  3203.   Flush_VMS_Object_Record_Buffer ();
  3204.   /*
  3205.    *    *************************
  3206.    *    *LANGUAGE PROCESSOR NAME*
  3207.    *    *************************
  3208.    *
  3209.    *    Store record type and header type
  3210.    */
  3211.   PUT_CHAR (OBJ_S_C_HDR);
  3212.   PUT_CHAR (MHD_S_C_LNM);
  3213.   /*
  3214.    *    Store language processor name and version
  3215.    *    (not a counted string!)
  3216.    */
  3217.   cp = compiler_version_string;
  3218.   if (cp == 0)
  3219.     {
  3220.       cp = "GNU AS  V";
  3221.       while (*cp)
  3222.     PUT_CHAR (*cp++);
  3223.       cp = strchr (GAS_VERSION, '.');
  3224.       while (*cp != ' ')
  3225.     cp--;
  3226.       cp++;
  3227.     };
  3228.   while (*cp >= 32)
  3229.     PUT_CHAR (*cp++);
  3230.   /*
  3231.    *    Flush the record
  3232.    */
  3233.   Flush_VMS_Object_Record_Buffer ();
  3234. }
  3235.  
  3236.  
  3237. /*
  3238.  *    Write the EOM (End Of Module) record
  3239.  */
  3240. static
  3241. Write_VMS_EOM_Record (Psect, Offset)
  3242.      int Psect;
  3243.      int Offset;
  3244. {
  3245.   /*
  3246.    *    We are writing an end-of-module record
  3247.    */
  3248.   Set_VMS_Object_File_Record (OBJ_S_C_EOM);
  3249.   /*
  3250.    *    Store record Type
  3251.    */
  3252.   PUT_CHAR (OBJ_S_C_EOM);
  3253.   /*
  3254.    *    Store the error severity (0)
  3255.    */
  3256.   PUT_CHAR (0);
  3257.   /*
  3258.    *    Store the entry point, if it exists
  3259.    */
  3260.   if (Psect >= 0)
  3261.     {
  3262.       /*
  3263.        *    Store the entry point Psect
  3264.        */
  3265.       PUT_CHAR (Psect);
  3266.       /*
  3267.        *    Store the entry point Psect offset
  3268.        */
  3269.       PUT_LONG (Offset);
  3270.     }
  3271.   /*
  3272.    *    Flush the record
  3273.    */
  3274.   Flush_VMS_Object_Record_Buffer ();
  3275. }
  3276.  
  3277.  
  3278. /* this hash routine borrowed from GNU-EMACS, and strengthened slightly  ERY*/
  3279.  
  3280. static int
  3281. hash_string (ptr)
  3282.      unsigned char *ptr;
  3283. {
  3284.   register unsigned char *p = ptr;
  3285.   register unsigned char *end = p + strlen (ptr);
  3286.   register unsigned char c;
  3287.   register int hash = 0;
  3288.  
  3289.   while (p != end)
  3290.     {
  3291.       c = *p++;
  3292.       hash = ((hash << 3) + (hash << 15) + (hash >> 28) + c);
  3293.     }
  3294.   return hash;
  3295. }
  3296.  
  3297. /*
  3298.  *    Generate a Case-Hacked VMS symbol name (limited to 31 chars)
  3299.  */
  3300. static
  3301. VMS_Case_Hack_Symbol (In, Out)
  3302.      register char *In;
  3303.      register char *Out;
  3304. {
  3305.   long int init = 0;
  3306.   long int result;
  3307.   char *pnt;
  3308.   char *new_name;
  3309.   char *old_name;
  3310.   register int i;
  3311.   int destructor = 0;        /*hack to allow for case sens in a destructor*/
  3312.   int truncate = 0;
  3313.   int Case_Hack_Bits = 0;
  3314.   int Saw_Dollar = 0;
  3315.   static char Hex_Table[16] =
  3316.   {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
  3317.  
  3318.   /*
  3319.    *    Kill any leading "_"
  3320.    */
  3321.   if ((In[0] == '_') && ((In[1] > '9') || (In[1] < '0')))
  3322.     In++;
  3323.  
  3324.   new_name = Out;        /* save this for later*/
  3325.  
  3326. #if barfoo            /* Dead code */
  3327.   if ((In[0] == '_') && (In[1] == '$') && (In[2] == '_'))
  3328.     destructor = 1;
  3329. #endif
  3330.  
  3331.   /* We may need to truncate the symbol, save the hash for later*/
  3332.   if (strlen (In) > 23)
  3333.     result = hash_string (In);
  3334.   /*
  3335.    *    Is there a Psect Attribute to skip??
  3336.    */
  3337.   if (HAS_PSECT_ATTRIBUTES (In))
  3338.     {
  3339.       /*
  3340.        *    Yes: Skip it
  3341.        */
  3342.       In += PSECT_ATTRIBUTES_STRING_LENGTH;
  3343.       while (*In)
  3344.     {
  3345.       if ((In[0] == '$') && (In[1] == '$'))
  3346.         {
  3347.           In += 2;
  3348.           break;
  3349.         }
  3350.       In++;
  3351.     }
  3352.     }
  3353.  
  3354.   old_name = In;
  3355. /*    if (strlen(In) > 31 && flagseen['+'])
  3356.         printf("%s: Symbol name truncated: %s\n",myname,In);*/
  3357.   /*
  3358.    *    Do the case conversion
  3359.    */
  3360.   i = 23;            /* Maximum of 23 chars */
  3361.   while (*In && (--i >= 0))
  3362.     {
  3363.       Case_Hack_Bits <<= 1;
  3364.       if (*In == '$')
  3365.     Saw_Dollar = 1;
  3366.       if ((destructor == 1) && (i == 21))
  3367.     Saw_Dollar = 0;
  3368.       switch (vms_name_mapping)
  3369.     {
  3370.     case 0:
  3371.       if (isupper(*In)) {
  3372.         *Out++ = *In++;
  3373.         Case_Hack_Bits |= 1;
  3374.       } else {
  3375.         *Out++ = islower(*In) ? toupper(*In++) : *In++;
  3376.       }
  3377.       break;
  3378.     case 3: *Out++ = *In++;
  3379.       break;
  3380.     case 2:
  3381.       if (islower(*In)) {
  3382.         *Out++ = *In++;
  3383.       } else {
  3384.         *Out++ = isupper(*In) ? tolower(*In++) : *In++;
  3385.       }
  3386.       break;
  3387.     };
  3388.     }
  3389.   /*
  3390.    *    If we saw a dollar sign, we don't do case hacking
  3391.    */
  3392.   if (flagseen['h'] || Saw_Dollar)
  3393.     Case_Hack_Bits = 0;
  3394.  
  3395.   /*
  3396.    *    If we have more than 23 characters and everything is lowercase
  3397.    *    we can insert the full 31 characters
  3398.    */
  3399.   if (*In)
  3400.     {
  3401.       /*
  3402.        *    We  have more than 23 characters
  3403.        * If we must add the case hack, then we have truncated the str
  3404.        */
  3405.       pnt = Out;
  3406.       truncate = 1;
  3407.       if (Case_Hack_Bits == 0)
  3408.     {
  3409.       /*
  3410.        *    And so far they are all lower case:
  3411.        *        Check up to 8 more characters
  3412.        *        and ensure that they are lowercase
  3413.        */
  3414.       for (i = 0; (In[i] != 0) && (i < 8); i++)
  3415.         if (isupper(In[i]) && !Saw_Dollar && !flagseen['h'])
  3416.           break;
  3417.  
  3418.       if (In[i] == 0)
  3419.         truncate = 0;
  3420.  
  3421.       if ((i == 8) || (In[i] == 0))
  3422.         {
  3423.           /*
  3424.            *    They are:  Copy up to 31 characters
  3425.            *            to the output string
  3426.            */
  3427.           i = 8;
  3428.           while ((--i >= 0) && (*In))
  3429.         switch (vms_name_mapping){
  3430.         case 0: *Out++ = islower(*In) ?
  3431.           toupper (*In++) :
  3432.             *In++;
  3433.           break;
  3434.         case 3: *Out++ = *In++;
  3435.           break;
  3436.         case 2: *Out++ = isupper(*In) ?
  3437.           tolower(*In++) :
  3438.             *In++;
  3439.           break;
  3440.         };
  3441.         }
  3442.     }
  3443.     }
  3444.   /*
  3445.    *    If there were any uppercase characters in the name we
  3446.    *    take on the case hacking string
  3447.    */
  3448.  
  3449.   /* Old behavior for regular GNU-C compiler */
  3450.   if (!flagseen['+'])
  3451.     truncate = 0;
  3452.   if ((Case_Hack_Bits != 0) || (truncate == 1))
  3453.     {
  3454.       if (truncate == 0)
  3455.     {
  3456.       *Out++ = '_';
  3457.       for (i = 0; i < 6; i++)
  3458.         {
  3459.           *Out++ = Hex_Table[Case_Hack_Bits & 0xf];
  3460.           Case_Hack_Bits >>= 4;
  3461.         }
  3462.       *Out++ = 'X';
  3463.     }
  3464.       else
  3465.     {
  3466.       Out = pnt;        /*Cut back to 23 characters maximum */
  3467.       *Out++ = '_';
  3468.       for (i = 0; i < 7; i++)
  3469.         {
  3470.           init = result & 0x01f;
  3471.           if (init < 10)
  3472.         *Out++ = '0' + init;
  3473.           else
  3474.         *Out++ = 'A' + init - 10;
  3475.           result = result >> 5;
  3476.         }
  3477.     }
  3478.     }                /*Case Hack */
  3479.   /*
  3480.    *    Done
  3481.    */
  3482.   *Out = 0;
  3483.   if (truncate == 1 && flagseen['+'] && flagseen['H'])
  3484.     printf ("%s: Symbol %s replaced by %s\n", myname, old_name, new_name);
  3485. }
  3486.  
  3487.  
  3488. /*
  3489.  *    Scan a symbol name for a psect attribute specification
  3490.  */
  3491. #define GLOBALSYMBOL_BIT    0x10000
  3492. #define GLOBALVALUE_BIT        0x20000
  3493.  
  3494.  
  3495. static
  3496. VMS_Modify_Psect_Attributes (Name, Attribute_Pointer)
  3497.      char *Name;
  3498.      int *Attribute_Pointer;
  3499. {
  3500.   register int i;
  3501.   register char *cp;
  3502.   int Negate;
  3503.   static struct
  3504.   {
  3505.     char *Name;
  3506.     int Value;
  3507.   } Attributes[] =
  3508.   {
  3509.     {"PIC", GPS_S_M_PIC},
  3510.     {"LIB", GPS_S_M_LIB},
  3511.     {"OVR", GPS_S_M_OVR},
  3512.     {"REL", GPS_S_M_REL},
  3513.     {"GBL", GPS_S_M_GBL},
  3514.     {"SHR", GPS_S_M_SHR},
  3515.     {"EXE", GPS_S_M_EXE},
  3516.     {"RD", GPS_S_M_RD},
  3517.     {"WRT", GPS_S_M_WRT},
  3518.     {"VEC", GPS_S_M_VEC},
  3519.     {"GLOBALSYMBOL", GLOBALSYMBOL_BIT},
  3520.     {"GLOBALVALUE", GLOBALVALUE_BIT},
  3521.     {0, 0}
  3522.   };
  3523.  
  3524.   /*
  3525.    *    Kill leading "_"
  3526.    */
  3527.   if (*Name == '_')
  3528.     Name++;
  3529.   /*
  3530.    *    Check for a PSECT attribute list
  3531.    */
  3532.   if (!HAS_PSECT_ATTRIBUTES (Name))
  3533.     return;            /* If not, return */
  3534.   /*
  3535.    *    Skip the attribute list indicator
  3536.    */
  3537.   Name += PSECT_ATTRIBUTES_STRING_LENGTH;
  3538.   /*
  3539.    *    Process the attributes ("_" separated, "$" terminated)
  3540.    */
  3541.   while (*Name != '$')
  3542.     {
  3543.       /*
  3544.        *    Assume not negating
  3545.        */
  3546.       Negate = 0;
  3547.       /*
  3548.        *    Check for "NO"
  3549.        */
  3550.       if ((Name[0] == 'N') && (Name[1] == 'O'))
  3551.     {
  3552.       /*
  3553.        *    We are negating (and skip the NO)
  3554.        */
  3555.       Negate = 1;
  3556.       Name += 2;
  3557.     }
  3558.       /*
  3559.        *    Find the token delimiter
  3560.        */
  3561.       cp = Name;
  3562.       while (*cp && (*cp != '_') && (*cp != '$'))
  3563.     cp++;
  3564.       /*
  3565.        *    Look for the token in the attribute list
  3566.        */
  3567.       for (i = 0; Attributes[i].Name; i++)
  3568.     {
  3569.       /*
  3570.        *    If the strings match, set/clear the attr.
  3571.        */
  3572.       if (strncmp (Name, Attributes[i].Name, cp - Name) == 0)
  3573.         {
  3574.           /*
  3575.            *    Set or clear
  3576.            */
  3577.           if (Negate)
  3578.         *Attribute_Pointer &=
  3579.           ~Attributes[i].Value;
  3580.           else
  3581.         *Attribute_Pointer |=
  3582.           Attributes[i].Value;
  3583.           /*
  3584.            *    Done
  3585.            */
  3586.           break;
  3587.         }
  3588.     }
  3589.       /*
  3590.        *    Now skip the attribute
  3591.        */
  3592.       Name = cp;
  3593.       if (*Name == '_')
  3594.     Name++;
  3595.     }
  3596.   /*
  3597.    *    Done
  3598.    */
  3599.   return;
  3600. }
  3601.  
  3602.  
  3603. /*
  3604.  *    Define a global symbol
  3605.  */
  3606. static
  3607. VMS_Global_Symbol_Spec (Name, Psect_Number, Psect_Offset, Defined)
  3608.      char *Name;
  3609.      int Psect_Number;
  3610.      int Psect_Offset;
  3611. {
  3612.   char Local[32];
  3613.  
  3614.   /*
  3615.    *    We are writing a GSD record
  3616.    */
  3617.   Set_VMS_Object_File_Record (OBJ_S_C_GSD);
  3618.   /*
  3619.    *    If the buffer is empty we must insert the GSD record type
  3620.    */
  3621.   if (Object_Record_Offset == 0)
  3622.     PUT_CHAR (OBJ_S_C_GSD);
  3623.   /*
  3624.    *    We are writing a Global symbol definition subrecord
  3625.    */
  3626.   if (Psect_Number <= 255)
  3627.     {
  3628.       PUT_CHAR (GSD_S_C_SYM);
  3629.     }
  3630.   else
  3631.     {
  3632.       PUT_CHAR (GSD_S_C_SYMW);
  3633.     }
  3634.   /*
  3635.    *    Data type is undefined
  3636.    */
  3637.   PUT_CHAR (0);
  3638.   /*
  3639.    *    Switch on Definition/Reference
  3640.    */
  3641.   if ((Defined & 1) != 0)
  3642.     {
  3643.       /*
  3644.        *    Definition:
  3645.        *    Flags = "RELOCATABLE" and "DEFINED" for regular symbol
  3646.        *          = "DEFINED" for globalvalue (Defined & 2 == 1)
  3647.        */
  3648.       if ((Defined & 2) == 0)
  3649.     {
  3650.       PUT_SHORT (GSY_S_M_DEF | GSY_S_M_REL);
  3651.     }
  3652.       else
  3653.     {
  3654.       PUT_SHORT (GSY_S_M_DEF);
  3655.     };
  3656.       /*
  3657.        *    Psect Number
  3658.        */
  3659.       if (Psect_Number <= 255)
  3660.     {
  3661.       PUT_CHAR (Psect_Number);
  3662.     }
  3663.       else
  3664.     {
  3665.       PUT_SHORT (Psect_Number);
  3666.     }
  3667.       /*
  3668.        *    Offset
  3669.        */
  3670.       PUT_LONG (Psect_Offset);
  3671.     }
  3672.   else
  3673.     {
  3674.       /*
  3675.        *    Reference:
  3676.        *    Flags = "RELOCATABLE" for regular symbol,
  3677.        *          = "" for globalvalue (Defined & 2 == 1)
  3678.        */
  3679.       if ((Defined & 2) == 0)
  3680.     {
  3681.       PUT_SHORT (GSY_S_M_REL);
  3682.     }
  3683.       else
  3684.     {
  3685.       PUT_SHORT (0);
  3686.     };
  3687.     }
  3688.   /*
  3689.    *    Finally, the global symbol name
  3690.    */
  3691.   VMS_Case_Hack_Symbol (Name, Local);
  3692.   PUT_COUNTED_STRING (Local);
  3693.   /*
  3694.    *    Flush the buffer if it is more than 75% full
  3695.    */
  3696.   if (Object_Record_Offset >
  3697.       (sizeof (Object_Record_Buffer) * 3 / 4))
  3698.     Flush_VMS_Object_Record_Buffer ();
  3699. }
  3700.  
  3701.  
  3702. /*
  3703.  *    Define a psect
  3704.  */
  3705. static int
  3706. VMS_Psect_Spec (Name, Size, Type, vsp)
  3707.      char *Name;
  3708.      int Size;
  3709.      char *Type;
  3710.      struct VMS_Symbol *vsp;
  3711. {
  3712.   char Local[32];
  3713.   int Psect_Attributes;
  3714.  
  3715.   /*
  3716.    *    Generate the appropriate PSECT flags given the PSECT type
  3717.    */
  3718.   if (strcmp (Type, "COMMON") == 0)
  3719.     {
  3720.       /*
  3721.        *    Common block psects are:  PIC,OVR,REL,GBL,SHR,RD,WRT
  3722.        */
  3723.       Psect_Attributes = (GPS_S_M_PIC | GPS_S_M_OVR | GPS_S_M_REL | GPS_S_M_GBL |
  3724.               GPS_S_M_SHR | GPS_S_M_RD | GPS_S_M_WRT);
  3725.     }
  3726.   else if (strcmp (Type, "CONST") == 0)
  3727.     {
  3728.       /*
  3729.        *    Common block psects are:  PIC,OVR,REL,GBL,SHR,RD
  3730.        */
  3731.       Psect_Attributes = (GPS_S_M_PIC | GPS_S_M_OVR | GPS_S_M_REL | GPS_S_M_GBL |
  3732.               GPS_S_M_SHR | GPS_S_M_RD);
  3733.     }
  3734.   else if (strcmp (Type, "DATA") == 0)
  3735.     {
  3736.       /*
  3737.        *    The Data psects are PIC,REL,RD,WRT
  3738.        */
  3739.       Psect_Attributes =
  3740.     (GPS_S_M_PIC | GPS_S_M_REL | GPS_S_M_RD | GPS_S_M_WRT);
  3741.     }
  3742.   else if (strcmp (Type, "TEXT") == 0)
  3743.     {
  3744.       /*
  3745.        *    The Text psects are PIC,REL,SHR,EXE,RD
  3746.        */
  3747.       Psect_Attributes =
  3748.     (GPS_S_M_PIC | GPS_S_M_REL | GPS_S_M_SHR |
  3749.      GPS_S_M_EXE | GPS_S_M_RD);
  3750.     }
  3751.   else
  3752.     {
  3753.       /*
  3754.        *    Error: Unknown psect type
  3755.        */
  3756.       error ("Unknown VMS psect type");
  3757.     }
  3758.   /*
  3759.    *    Modify the psect attributes according to any attribute string
  3760.    */
  3761.   if (HAS_PSECT_ATTRIBUTES (Name))
  3762.     VMS_Modify_Psect_Attributes (Name, &Psect_Attributes);
  3763.   /*
  3764.    *    Check for globalref/def/val.
  3765.    */
  3766.   if ((Psect_Attributes & GLOBALVALUE_BIT) != 0)
  3767.     {
  3768.       /*
  3769.        * globalvalue symbols were generated before. This code
  3770.        * prevents unsightly psect buildup, and makes sure that
  3771.        * fixup references are emitted correctly.
  3772.        */
  3773.       vsp->Psect_Index = -1;    /* to catch errors */
  3774.       S_GET_RAW_TYPE (vsp->Symbol) = N_UNDF;    /* make refs work */
  3775.       return 1;            /* decrement psect counter */
  3776.     };
  3777.  
  3778.   if ((Psect_Attributes & GLOBALSYMBOL_BIT) != 0)
  3779.     {
  3780.       switch (S_GET_RAW_TYPE (vsp->Symbol))
  3781.     {
  3782.     case N_UNDF | N_EXT:
  3783.       VMS_Global_Symbol_Spec (Name, vsp->Psect_Index,
  3784.                   vsp->Psect_Offset, 0);
  3785.       vsp->Psect_Index = -1;
  3786.       S_GET_RAW_TYPE (vsp->Symbol) = N_UNDF;
  3787.       return 1;        /* return and indicate no psect */
  3788.     case N_DATA | N_EXT:
  3789.       VMS_Global_Symbol_Spec (Name, vsp->Psect_Index,
  3790.                   vsp->Psect_Offset, 1);
  3791.       /* In this case we still generate the psect */
  3792.       break;
  3793.     default:
  3794.       {
  3795.         char Error_Line[256];
  3796.         sprintf (Error_Line,
  3797.              "Globalsymbol attribute for symbol %s was unexpected.\n",
  3798.              Name);
  3799.         error (Error_Line);
  3800.         break;
  3801.       };
  3802.     };            /* switch */
  3803.     };
  3804.  
  3805.   Psect_Attributes &= 0xffff;    /* clear out the globalref/def stuff */
  3806.   /*
  3807.    *    We are writing a GSD record
  3808.    */
  3809.   Set_VMS_Object_File_Record (OBJ_S_C_GSD);
  3810.   /*
  3811.    *    If the buffer is empty we must insert the GSD record type
  3812.    */
  3813.   if (Object_Record_Offset == 0)
  3814.     PUT_CHAR (OBJ_S_C_GSD);
  3815.   /*
  3816.    *    We are writing a PSECT definition subrecord
  3817.    */
  3818.   PUT_CHAR (GSD_S_C_PSC);
  3819.   /*
  3820.    *    Psects are always LONGWORD aligned
  3821.    */
  3822.   PUT_CHAR (2);
  3823.   /*
  3824.    *    Specify the psect attributes
  3825.    */
  3826.   PUT_SHORT (Psect_Attributes);
  3827.   /*
  3828.    *    Specify the allocation
  3829.    */
  3830.   PUT_LONG (Size);
  3831.   /*
  3832.    *    Finally, the psect name
  3833.    */
  3834.   VMS_Case_Hack_Symbol (Name, Local);
  3835.   PUT_COUNTED_STRING (Local);
  3836.   /*
  3837.    *    Flush the buffer if it is more than 75% full
  3838.    */
  3839.   if (Object_Record_Offset >
  3840.       (sizeof (Object_Record_Buffer) * 3 / 4))
  3841.     Flush_VMS_Object_Record_Buffer ();
  3842.   return 0;
  3843. }
  3844.  
  3845.  
  3846. /*
  3847.  *    Given the pointer to a symbol we calculate how big the data at the
  3848.  *    symbol is.  We do this by looking for the next symbol (local or
  3849.  *    global) which will indicate the start of another datum.
  3850.  */
  3851. static int
  3852. VMS_Initialized_Data_Size (sp, End_Of_Data)
  3853.      register struct symbol *sp;
  3854.      int End_Of_Data;
  3855. {
  3856.   register struct symbol *sp1, *Next_Symbol;
  3857.  
  3858.   /*
  3859.    *    Find the next symbol
  3860.    *    it delimits this datum
  3861.    */
  3862.   Next_Symbol = 0;
  3863.   for (sp1 = symbol_rootP; sp1; sp1 = symbol_next (sp1))
  3864.     {
  3865.       /*
  3866.        *    The data type must match
  3867.        */
  3868.       if (S_GET_TYPE (sp1) != N_DATA)
  3869.     continue;
  3870.       /*
  3871.        *    The symbol must be AFTER this symbol
  3872.        */
  3873.       if (S_GET_VALUE (sp1) <= S_GET_VALUE (sp))
  3874.     continue;
  3875.       /*
  3876.        *    We ignore THIS symbol
  3877.        */
  3878.       if (sp1 == sp)
  3879.     continue;
  3880.       /*
  3881.        *    If there is already a candidate selected for the
  3882.        *    next symbol, see if we are a better candidate
  3883.        */
  3884.       if (Next_Symbol)
  3885.     {
  3886.       /*
  3887.        *    We are a better candidate if we are "closer"
  3888.        *    to the symbol
  3889.        */
  3890.       if (S_GET_VALUE (sp1) >
  3891.           S_GET_VALUE (Next_Symbol))
  3892.         continue;
  3893.       /*
  3894.        *    Win:  Make this the candidate
  3895.        */
  3896.       Next_Symbol = sp1;
  3897.     }
  3898.       else
  3899.     {
  3900.       /*
  3901.        *    This is the 1st candidate
  3902.        */
  3903.       Next_Symbol = sp1;
  3904.     }
  3905.     }
  3906.   /*
  3907.    *    Calculate its size
  3908.    */
  3909.   return (Next_Symbol ?
  3910.       (S_GET_VALUE (Next_Symbol) -
  3911.        S_GET_VALUE (sp)) :
  3912.       (End_Of_Data - S_GET_VALUE (sp)));
  3913. }
  3914.  
  3915. /*
  3916.  *    Check symbol names for the Psect hack with a globalvalue, and then
  3917.  *    generate globalvalues for those that have it.
  3918.  */
  3919. static
  3920. VMS_Emit_Globalvalues (text_siz, data_siz, Data_Segment)
  3921.      unsigned text_siz;
  3922.      unsigned data_siz;
  3923.      char *Data_Segment;
  3924. {
  3925.   register symbolS *sp;
  3926.   char *stripped_name, *Name;
  3927.   int Size;
  3928.   int Psect_Attributes;
  3929.   int globalvalue;
  3930.  
  3931.   /*
  3932.    * Scan the symbol table for globalvalues, and emit def/ref when
  3933.    * required.  These will be caught again later and converted to
  3934.    * N_UNDF
  3935.    */
  3936.   for (sp = symbol_rootP; sp; sp = sp->sy_next)
  3937.     {
  3938.       /*
  3939.        *    See if this is something we want to look at.
  3940.        */
  3941.       if ((S_GET_RAW_TYPE (sp) != (N_DATA | N_EXT)) &&
  3942.       (S_GET_RAW_TYPE (sp) != (N_UNDF | N_EXT)))
  3943.     continue;
  3944.       /*
  3945.        *    See if this has globalvalue specification.
  3946.        */
  3947.       Name = S_GET_NAME (sp);
  3948.  
  3949.       if (!HAS_PSECT_ATTRIBUTES (Name))
  3950.     continue;
  3951.  
  3952.       stripped_name = (char *) malloc (strlen (Name) + 1);
  3953.       strcpy (stripped_name, Name);
  3954.       Psect_Attributes = 0;
  3955.       VMS_Modify_Psect_Attributes (stripped_name, &Psect_Attributes);
  3956.  
  3957.       if ((Psect_Attributes & GLOBALVALUE_BIT) != 0)
  3958.     {
  3959.       switch (S_GET_RAW_TYPE (sp))
  3960.         {
  3961.         case N_UNDF | N_EXT:
  3962.           VMS_Global_Symbol_Spec (stripped_name, 0, 0, 2);
  3963.           break;
  3964.         case N_DATA | N_EXT:
  3965.           Size = VMS_Initialized_Data_Size (sp, text_siz + data_siz);
  3966.           if (Size > 4)
  3967.         error ("Invalid data type for globalvalue");
  3968.           globalvalue = md_chars_to_number (Data_Segment + 
  3969.              S_GET_VALUE (sp) - text_siz , Size);
  3970.           /* Three times for good luck.  The linker seems to get confused
  3971.              if there are fewer than three */
  3972.           VMS_Global_Symbol_Spec (stripped_name, 0, 0, 2);
  3973.           VMS_Global_Symbol_Spec (stripped_name, 0, globalvalue, 3);
  3974.           VMS_Global_Symbol_Spec (stripped_name, 0, globalvalue, 3);
  3975.           break;
  3976.         default:
  3977.           printf (" Invalid globalvalue of %s\n", stripped_name);
  3978.           break;
  3979.         };            /* switch */
  3980.     };            /* if */
  3981.       free (stripped_name);    /* clean up */
  3982.     };                /* for */
  3983.  
  3984. }
  3985.  
  3986.  
  3987. /*
  3988.  *    Define a procedure entry pt/mask
  3989.  */
  3990. static
  3991. VMS_Procedure_Entry_Pt (Name, Psect_Number, Psect_Offset, Entry_Mask)
  3992.      char *Name;
  3993.      int Psect_Number;
  3994.      int Psect_Offset;
  3995.      int Entry_Mask;
  3996. {
  3997.   char Local[32];
  3998.  
  3999.   /*
  4000.    *    We are writing a GSD record
  4001.    */
  4002.   Set_VMS_Object_File_Record (OBJ_S_C_GSD);
  4003.   /*
  4004.    *    If the buffer is empty we must insert the GSD record type
  4005.    */
  4006.   if (Object_Record_Offset == 0)
  4007.     PUT_CHAR (OBJ_S_C_GSD);
  4008.   /*
  4009.    *    We are writing a Procedure Entry Pt/Mask subrecord
  4010.    */
  4011.   if (Psect_Number <= 255)
  4012.     {
  4013.       PUT_CHAR (GSD_S_C_EPM);
  4014.     }
  4015.   else
  4016.     {
  4017.       PUT_CHAR (GSD_S_C_EPMW);
  4018.     }
  4019.   /*
  4020.    *    Data type is undefined
  4021.    */
  4022.   PUT_CHAR (0);
  4023.   /*
  4024.    *    Flags = "RELOCATABLE" and "DEFINED"
  4025.    */
  4026.   PUT_SHORT (GSY_S_M_DEF | GSY_S_M_REL);
  4027.   /*
  4028.    *    Psect Number
  4029.    */
  4030.   if (Psect_Number <= 255)
  4031.     {
  4032.       PUT_CHAR (Psect_Number);
  4033.     }
  4034.   else
  4035.     {
  4036.       PUT_SHORT (Psect_Number);
  4037.     }
  4038.   /*
  4039.    *    Offset
  4040.    */
  4041.   PUT_LONG (Psect_Offset);
  4042.   /*
  4043.    *    Entry mask
  4044.    */
  4045.   PUT_SHORT (Entry_Mask);
  4046.   /*
  4047.    *    Finally, the global symbol name
  4048.    */
  4049.   VMS_Case_Hack_Symbol (Name, Local);
  4050.   PUT_COUNTED_STRING (Local);
  4051.   /*
  4052.    *    Flush the buffer if it is more than 75% full
  4053.    */
  4054.   if (Object_Record_Offset >
  4055.       (sizeof (Object_Record_Buffer) * 3 / 4))
  4056.     Flush_VMS_Object_Record_Buffer ();
  4057. }
  4058.  
  4059.  
  4060. /*
  4061.  *    Set the current location counter to a particular Psect and Offset
  4062.  */
  4063. static
  4064. VMS_Set_Psect (Psect_Index, Offset, Record_Type)
  4065.      int Psect_Index;
  4066.      int Offset;
  4067.      int Record_Type;
  4068. {
  4069.   /*
  4070.    *    We are writing a "Record_Type" record
  4071.    */
  4072.   Set_VMS_Object_File_Record (Record_Type);
  4073.   /*
  4074.    *    If the buffer is empty we must insert the record type
  4075.    */
  4076.   if (Object_Record_Offset == 0)
  4077.     PUT_CHAR (Record_Type);
  4078.   /*
  4079.    *    Stack the Psect base + Longword Offset
  4080.    */
  4081.   if (Psect_Index < 255)
  4082.     {
  4083.       PUT_CHAR (TIR_S_C_STA_PL);
  4084.       PUT_CHAR (Psect_Index);
  4085.     }
  4086.   else
  4087.     {
  4088.       PUT_CHAR (TIR_S_C_STA_WPL);
  4089.       PUT_SHORT (Psect_Index);
  4090.     }
  4091.   PUT_LONG (Offset);
  4092.   /*
  4093.    *    Set relocation base
  4094.    */
  4095.   PUT_CHAR (TIR_S_C_CTL_SETRB);
  4096.   /*
  4097.    *    Flush the buffer if it is more than 75% full
  4098.    */
  4099.   if (Object_Record_Offset >
  4100.       (sizeof (Object_Record_Buffer) * 3 / 4))
  4101.     Flush_VMS_Object_Record_Buffer ();
  4102. }
  4103.  
  4104.  
  4105. /*
  4106.  *    Store repeated immediate data in current Psect
  4107.  */
  4108. static
  4109. VMS_Store_Repeated_Data (Repeat_Count, Pointer, Size, Record_Type)
  4110.      int Repeat_Count;
  4111.      register char *Pointer;
  4112.      int Size;
  4113.      int Record_Type;
  4114. {
  4115.  
  4116.   /*
  4117.    *    Ignore zero bytes/words/longwords
  4118.    */
  4119.   if ((Size == sizeof (char)) && (*Pointer == 0))
  4120.     return;
  4121.   if ((Size == sizeof (short)) && (*(short *) Pointer == 0))
  4122.     return;
  4123.   if ((Size == sizeof (long)) && (*(long *) Pointer == 0))
  4124.     return;
  4125.   /*
  4126.    *    If the data is too big for a TIR_S_C_STO_RIVB sub-record
  4127.    *    then we do it manually
  4128.    */
  4129.   if (Size > 255)
  4130.     {
  4131.       while (--Repeat_Count >= 0)
  4132.     VMS_Store_Immediate_Data (Pointer, Size, Record_Type);
  4133.       return;
  4134.     }
  4135.   /*
  4136.    *    We are writing a "Record_Type" record
  4137.    */
  4138.   Set_VMS_Object_File_Record (Record_Type);
  4139.   /*
  4140.    *    If the buffer is empty we must insert record type
  4141.    */
  4142.   if (Object_Record_Offset == 0)
  4143.     PUT_CHAR (Record_Type);
  4144.   /*
  4145.    *    Stack the repeat count
  4146.    */
  4147.   PUT_CHAR (TIR_S_C_STA_LW);
  4148.   PUT_LONG (Repeat_Count);
  4149.   /*
  4150.    *    And now the command and its data
  4151.    */
  4152.   PUT_CHAR (TIR_S_C_STO_RIVB);
  4153.   PUT_CHAR (Size);
  4154.   while (--Size >= 0)
  4155.     PUT_CHAR (*Pointer++);
  4156.   /*
  4157.    *    Flush the buffer if it is more than 75% full
  4158.    */
  4159.   if (Object_Record_Offset >
  4160.       (sizeof (Object_Record_Buffer) * 3 / 4))
  4161.     Flush_VMS_Object_Record_Buffer ();
  4162. }
  4163.  
  4164.  
  4165. /*
  4166.  *    Store a Position Independent Reference
  4167.  */
  4168. static
  4169. VMS_Store_PIC_Symbol_Reference (Symbol, Offset, PC_Relative,
  4170.                 Psect, Psect_Offset, Record_Type)
  4171.      struct symbol *Symbol;
  4172.      int Offset;
  4173.      int PC_Relative;
  4174.      int Psect;
  4175.      int Psect_Offset;
  4176.      int Record_Type;
  4177. {
  4178.   register struct VMS_Symbol *vsp =
  4179.   (struct VMS_Symbol *) (Symbol->sy_number);
  4180.   char Local[32];
  4181.  
  4182.   /*
  4183.    *    We are writing a "Record_Type" record
  4184.    */
  4185.   Set_VMS_Object_File_Record (Record_Type);
  4186.   /*
  4187.    *    If the buffer is empty we must insert record type
  4188.    */
  4189.   if (Object_Record_Offset == 0)
  4190.     PUT_CHAR (Record_Type);
  4191.   /*
  4192.    *    Set to the appropriate offset in the Psect
  4193.    */
  4194.   if (PC_Relative)
  4195.     {
  4196.       /*
  4197.        *    For a Code reference we need to fix the operand
  4198.        *    specifier as well (so back up 1 byte)
  4199.        */
  4200.       VMS_Set_Psect (Psect, Psect_Offset - 1, Record_Type);
  4201.     }
  4202.   else
  4203.     {
  4204.       /*
  4205.        *    For a Data reference we just store HERE
  4206.        */
  4207.       VMS_Set_Psect (Psect, Psect_Offset, Record_Type);
  4208.     }
  4209.   /*
  4210.    *    Make sure we are still generating a "Record Type" record
  4211.    */
  4212.   if (Object_Record_Offset == 0)
  4213.     PUT_CHAR (Record_Type);
  4214.   /*
  4215.    *    Dispatch on symbol type (so we can stack its value)
  4216.    */
  4217.   switch (S_GET_RAW_TYPE (Symbol))
  4218.     {
  4219.       /*
  4220.        *    Global symbol
  4221.        */
  4222. #ifdef    NOT_VAX_11_C_COMPATIBLE
  4223.     case N_UNDF | N_EXT:
  4224.     case N_DATA | N_EXT:
  4225. #endif    /* NOT_VAX_11_C_COMPATIBLE */
  4226.     case N_UNDF:
  4227.     case N_TEXT | N_EXT:
  4228.       /*
  4229.        *    Get the symbol name (case hacked)
  4230.        */
  4231.       VMS_Case_Hack_Symbol (S_GET_NAME (Symbol), Local);
  4232.       /*
  4233.        *    Stack the global symbol value
  4234.        */
  4235.       PUT_CHAR (TIR_S_C_STA_GBL);
  4236.       PUT_COUNTED_STRING (Local);
  4237.       if (Offset)
  4238.     {
  4239.       /*
  4240.        *    Stack the longword offset
  4241.        */
  4242.       PUT_CHAR (TIR_S_C_STA_LW);
  4243.       PUT_LONG (Offset);
  4244.       /*
  4245.        *    Add the two, leaving the result on the stack
  4246.        */
  4247.       PUT_CHAR (TIR_S_C_OPR_ADD);
  4248.     }
  4249.       break;
  4250.       /*
  4251.        *    Uninitialized local data
  4252.        */
  4253.     case N_BSS:
  4254.       /*
  4255.        *    Stack the Psect (+offset)
  4256.        */
  4257.       if (vsp->Psect_Index < 255)
  4258.     {
  4259.       PUT_CHAR (TIR_S_C_STA_PL);
  4260.       PUT_CHAR (vsp->Psect_Index);
  4261.     }
  4262.       else
  4263.     {
  4264.       PUT_CHAR (TIR_S_C_STA_WPL);
  4265.       PUT_SHORT (vsp->Psect_Index);
  4266.     }
  4267.       PUT_LONG (vsp->Psect_Offset + Offset);
  4268.       break;
  4269.       /*
  4270.        *    Local text
  4271.        */
  4272.     case N_TEXT:
  4273.       /*
  4274.        *    Stack the Psect (+offset)
  4275.        */
  4276.       if (vsp->Psect_Index < 255)
  4277.     {
  4278.       PUT_CHAR (TIR_S_C_STA_PL);
  4279.       PUT_CHAR (vsp->Psect_Index);
  4280.     }
  4281.       else
  4282.     {
  4283.       PUT_CHAR (TIR_S_C_STA_WPL);
  4284.       PUT_SHORT (vsp->Psect_Index);
  4285.     }
  4286.       PUT_LONG (S_GET_VALUE (Symbol) + Offset);
  4287.       break;
  4288.       /*
  4289.        *    Initialized local or global data
  4290.        */
  4291.     case N_DATA:
  4292. #ifndef    NOT_VAX_11_C_COMPATIBLE
  4293.     case N_UNDF | N_EXT:
  4294.     case N_DATA | N_EXT:
  4295. #endif    /* NOT_VAX_11_C_COMPATIBLE */
  4296.       /*
  4297.        *    Stack the Psect (+offset)
  4298.        */
  4299.       if (vsp->Psect_Index < 255)
  4300.     {
  4301.       PUT_CHAR (TIR_S_C_STA_PL);
  4302.       PUT_CHAR (vsp->Psect_Index);
  4303.     }
  4304.       else
  4305.     {
  4306.       PUT_CHAR (TIR_S_C_STA_WPL);
  4307.       PUT_SHORT (vsp->Psect_Index);
  4308.     }
  4309.       PUT_LONG (vsp->Psect_Offset + Offset);
  4310.       break;
  4311.     }
  4312.   /*
  4313.    *    Store either a code or data reference
  4314.    */
  4315.   PUT_CHAR (PC_Relative ? TIR_S_C_STO_PICR : TIR_S_C_STO_PIDR);
  4316.   /*
  4317.    *    Flush the buffer if it is more than 75% full
  4318.    */
  4319.   if (Object_Record_Offset >
  4320.       (sizeof (Object_Record_Buffer) * 3 / 4))
  4321.     Flush_VMS_Object_Record_Buffer ();
  4322. }
  4323.  
  4324.  
  4325. /*
  4326.  *    Check in the text area for an indirect pc-relative reference
  4327.  *    and fix it up with addressing mode 0xff [PC indirect]
  4328.  *
  4329.  *    THIS SHOULD BE REPLACED BY THE USE OF TIR_S_C_STO_PIRR IN THE
  4330.  *    PIC CODE GENERATING FIXUP ROUTINE.
  4331.  */
  4332. static
  4333. VMS_Fix_Indirect_Reference (Text_Psect, Offset, fragP, text_frag_root)
  4334.      int Text_Psect;
  4335.      int Offset;
  4336.      register fragS *fragP;
  4337.      struct frag *text_frag_root;
  4338. {
  4339.   /*
  4340.    *    The addressing mode byte is 1 byte before the address
  4341.    */
  4342.   Offset--;
  4343.   /*
  4344.    *    Is it in THIS frag??
  4345.    */
  4346.   if ((Offset < fragP->fr_address) ||
  4347.       (Offset >= (fragP->fr_address + fragP->fr_fix)))
  4348.     {
  4349.       /*
  4350.        *    We need to search for the fragment containing this
  4351.        *    Offset
  4352.        */
  4353.       for (fragP = text_frag_root; fragP; fragP = fragP->fr_next)
  4354.     {
  4355.       if ((Offset >= fragP->fr_address) &&
  4356.           (Offset < (fragP->fr_address + fragP->fr_fix)))
  4357.         break;
  4358.     }
  4359.       /*
  4360.        *    If we couldn't find the frag, things are BAD!!
  4361.        */
  4362.       if (fragP == 0)
  4363.     error ("Couldn't find fixup fragment when checking for indirect reference");
  4364.     }
  4365.   /*
  4366.    *    Check for indirect PC relative addressing mode
  4367.    */
  4368.   if (fragP->fr_literal[Offset - fragP->fr_address] == (char) 0xff)
  4369.     {
  4370.       static char Address_Mode = 0xff;
  4371.  
  4372.       /*
  4373.        *    Yes: Store the indirect mode back into the image
  4374.        *         to fix up the damage done by STO_PICR
  4375.        */
  4376.       VMS_Set_Psect (Text_Psect, Offset, OBJ_S_C_TIR);
  4377.       VMS_Store_Immediate_Data (&Address_Mode, 1, OBJ_S_C_TIR);
  4378.     }
  4379. }
  4380.  
  4381. /*
  4382.  *    If the procedure "main()" exists we have to add the instruction
  4383.  *    "jsb c$main_args" at the beginning to be compatible with VAX-11 "C".
  4384.  */
  4385. VMS_Check_For_Main ()
  4386. {
  4387.   register symbolS *symbolP;
  4388. #ifdef    HACK_DEC_C_STARTUP    /* JF */
  4389.   register struct frchain *frchainP;
  4390.   register fragS *fragP;
  4391.   register fragS **prev_fragPP;
  4392.   register struct fix *fixP;
  4393.   register fragS *New_Frag;
  4394.   int i;
  4395. #endif    /* HACK_DEC_C_STARTUP */
  4396.  
  4397.   symbolP = (struct symbol *) symbol_find ("_main");
  4398.   if (symbolP && !S_IS_DEBUG (symbolP) &&
  4399.       S_IS_EXTERNAL (symbolP) && (S_GET_TYPE (symbolP) == N_TEXT))
  4400.     {
  4401. #ifdef    HACK_DEC_C_STARTUP
  4402.       if (!flagseen['+'])
  4403.     {
  4404. #endif
  4405.       /*
  4406.        *    Remember the entry point symbol
  4407.        */
  4408.       Entry_Point_Symbol = symbolP;
  4409. #ifdef HACK_DEC_C_STARTUP
  4410.     }
  4411.       else
  4412.     {
  4413.       /*
  4414.        *    Scan all the fragment chains for the one with "_main"
  4415.        *    (Actually we know the fragment from the symbol, but we need
  4416.        *     the previous fragment so we can change its pointer)
  4417.        */
  4418.       frchainP = frchain_root;
  4419.       while (frchainP)
  4420.         {
  4421.           /*
  4422.            *    Scan all the fragments in this chain, remembering
  4423.            *    the "previous fragment"
  4424.            */
  4425.           prev_fragPP = &frchainP->frch_root;
  4426.           fragP = frchainP->frch_root;
  4427.           while (fragP && (fragP != frchainP->frch_last))
  4428.         {
  4429.           /*
  4430.            *    Is this the fragment?
  4431.            */
  4432.           if (fragP == symbolP->sy_frag)
  4433.             {
  4434.               /*
  4435.                *    Yes: Modify the fragment by replacing
  4436.                *         it with a new fragment.
  4437.                */
  4438.               New_Frag = (fragS *)
  4439.             xmalloc (sizeof (*New_Frag) +
  4440.                  fragP->fr_fix +
  4441.                  fragP->fr_var +
  4442.                  5);
  4443.               /*
  4444.                *    The fragments are the same except
  4445.                *    that the "fixed" area is larger
  4446.                */
  4447.               *New_Frag = *fragP;
  4448.               New_Frag->fr_fix += 6;
  4449.               /*
  4450.                *    Copy the literal data opening a hole
  4451.                *    2 bytes after "_main" (i.e. just after
  4452.                *    the entry mask).  Into which we place
  4453.                *    the JSB instruction.
  4454.                */
  4455.               New_Frag->fr_literal[0] = fragP->fr_literal[0];
  4456.               New_Frag->fr_literal[1] = fragP->fr_literal[1];
  4457.               New_Frag->fr_literal[2] = 0x16;    /* Jsb */
  4458.               New_Frag->fr_literal[3] = 0xef;
  4459.               New_Frag->fr_literal[4] = 0;
  4460.               New_Frag->fr_literal[5] = 0;
  4461.               New_Frag->fr_literal[6] = 0;
  4462.               New_Frag->fr_literal[7] = 0;
  4463.               for (i = 2; i < fragP->fr_fix + fragP->fr_var; i++)
  4464.             New_Frag->fr_literal[i + 6] =
  4465.               fragP->fr_literal[i];
  4466.               /*
  4467.                *    Now replace the old fragment with the
  4468.                *    newly generated one.
  4469.                */
  4470.               *prev_fragPP = New_Frag;
  4471.               /*
  4472.                *    Remember the entry point symbol
  4473.                */
  4474.               Entry_Point_Symbol = symbolP;
  4475.               /*
  4476.                *    Scan the text area fixup structures
  4477.                *    as offsets in the fragment may have
  4478.                *    changed
  4479.                */
  4480.               for (fixP = text_fix_root; fixP; fixP = fixP->fx_next)
  4481.             {
  4482.               /*
  4483.                *    Look for references to this
  4484.                *    fragment.
  4485.                */
  4486.               if (fixP->fx_frag == fragP)
  4487.                 {
  4488.                   /*
  4489.                    *    Change the fragment
  4490.                    *    pointer
  4491.                    */
  4492.                   fixP->fx_frag = New_Frag;
  4493.                   /*
  4494.                    *    If the offset is after
  4495.                    *    the entry mask we need
  4496.                    *    to account for the JSB
  4497.                    *    instruction we just
  4498.                    *    inserted.
  4499.                    */
  4500.                   if (fixP->fx_where >= 2)
  4501.                 fixP->fx_where += 6;
  4502.                 }
  4503.             }
  4504.               /*
  4505.                *    Scan the symbols as offsets in the
  4506.                *    fragment may have changed
  4507.                */
  4508.               for (symbolP = symbol_rootP;
  4509.                symbolP;
  4510.                symbolP = symbol_next (symbolP))
  4511.             {
  4512.               /*
  4513.                *    Look for references to this
  4514.                *    fragment.
  4515.                */
  4516.               if (symbolP->sy_frag == fragP)
  4517.                 {
  4518.                   /*
  4519.                    *    Change the fragment
  4520.                    *    pointer
  4521.                    */
  4522.                   symbolP->sy_frag = New_Frag;
  4523.                   /*
  4524.                    *    If the offset is after
  4525.                    *    the entry mask we need
  4526.                    *    to account for the JSB
  4527.                    *    instruction we just
  4528.                    *    inserted.
  4529.                    */
  4530.                   if (S_GET_VALUE (symbolP) >= 2)
  4531.                 S_GET_VALUE (symbolP) += 6;
  4532.                 }
  4533.             }
  4534.               /*
  4535.                *    Make a symbol reference to
  4536.                *    "_c$main_args" so we can get
  4537.                *    its address inserted into the
  4538.                *    JSB instruction.
  4539.                */
  4540.               symbolP = (symbolS *) xmalloc (sizeof (*symbolP));
  4541.               S_GET_NAME (symbolP) = "_c$main_args";
  4542.               S_SET_TYPE (symbolP, N_UNDF);
  4543.               S_GET_OTHER (symbolP) = 0;
  4544.               S_GET_DESC (symbolP) = 0;
  4545.               S_GET_VALUE (symbolP) = 0;
  4546.               symbolP->sy_name_offset = 0;
  4547.               symbolP->sy_number = 0;
  4548.               symbolP->sy_frag = New_Frag;
  4549.               symbolP->sy_forward = 0;
  4550.               /* this actually inserts at the beginning of the list */
  4551.               symbol_append (symbol_rootP, symbolP, &symbol_rootP, &symbol_lastP);
  4552.  
  4553.               symbol_rootP = symbolP;
  4554.               /*
  4555.                *    Generate a text fixup structure
  4556.                *    to get "_c$main_args" stored into the
  4557.                *    JSB instruction.
  4558.                */
  4559.               fixP = (struct fix *) xmalloc (sizeof (*fixP));
  4560.               fixP->fx_frag = New_Frag;
  4561.               fixP->fx_where = 4;
  4562.               fixP->fx_addsy = symbolP;
  4563.               fixP->fx_subsy = 0;
  4564.               fixP->fx_offset = 0;
  4565.               fixP->fx_size = sizeof (long);
  4566.               fixP->fx_pcrel = 1;
  4567.               fixP->fx_next = text_fix_root;
  4568.               text_fix_root = fixP;
  4569.               /*
  4570.                *    Now make sure we exit from the loop
  4571.                */
  4572.               frchainP = 0;
  4573.               break;
  4574.             }
  4575.           /*
  4576.            *    Try the next fragment
  4577.            */
  4578.           prev_fragPP = &fragP->fr_next;
  4579.           fragP = fragP->fr_next;
  4580.         }
  4581.           /*
  4582.            *    Try the next fragment chain
  4583.            */
  4584.           if (frchainP)
  4585.         frchainP = frchainP->frch_next;
  4586.         }
  4587.     }
  4588. #endif /* HACK_DEC_C_STARTUP */
  4589.     }
  4590. }
  4591.  
  4592. /*
  4593.  *    Write a VAX/VMS object file (everything else has been done!)
  4594.  */
  4595. VMS_write_object_file (text_siz, data_siz, bss_siz, text_frag_root,
  4596.                data_frag_root)
  4597.      unsigned text_siz;
  4598.      unsigned data_siz;
  4599.      unsigned bss_siz;
  4600.      struct frag *text_frag_root;
  4601.      struct frag *data_frag_root;
  4602. {
  4603.   register fragS *fragP;
  4604.   register symbolS *symbolP;
  4605.   register symbolS *sp;
  4606.   register struct fix *fixP;
  4607.   register struct VMS_Symbol *vsp;
  4608.   char *Data_Segment;
  4609.   int Local_Initialized_Data_Size = 0;
  4610.   int Globalref;
  4611.   int Psect_Number = 0;        /* Psect Index Number */
  4612.   int Text_Psect = -1;        /* Text Psect Index   */
  4613.   int Data_Psect = -2;        /* Data Psect Index   JF: Was -1 */
  4614.   int Bss_Psect = -3;        /* Bss Psect Index    JF: Was -1 */
  4615.  
  4616.   /*
  4617.    *    Create the VMS object file
  4618.    */
  4619.   Create_VMS_Object_File ();
  4620.   /*
  4621.    *    Write the module header records
  4622.    */
  4623.   Write_VMS_MHD_Records ();
  4624.  
  4625.   /*
  4626.    *    Store the Data segment:
  4627.    *
  4628.    *    Since this is REALLY hard to do any other way,
  4629.    *    we actually manufacture the data segment and
  4630.    *    the store the appropriate values out of it.
  4631.    *    We need to generate this early, so that globalvalues
  4632.    *    can be properly emitted.
  4633.    */
  4634.   if (data_siz > 0)
  4635.     {
  4636.       /*
  4637.        *    Allocate the data segment
  4638.        */
  4639.       Data_Segment = (char *) xmalloc (data_siz);
  4640.       /*
  4641.        *    Run through the data fragments, filling in the segment
  4642.        */
  4643.       for (fragP = data_frag_root; fragP; fragP = fragP->fr_next)
  4644.     {
  4645.       register long int count;
  4646.       register char *fill_literal;
  4647.       register long int fill_size;
  4648.       int i;
  4649.  
  4650.       i = fragP->fr_address - text_siz;
  4651.       if (fragP->fr_fix)
  4652.         memcpy (Data_Segment + i,
  4653.             fragP->fr_literal,
  4654.             fragP->fr_fix);
  4655.       i += fragP->fr_fix;
  4656.  
  4657.       fill_literal = fragP->fr_literal + fragP->fr_fix;
  4658.       fill_size = fragP->fr_var;
  4659.       for (count = fragP->fr_offset; count; count--)
  4660.         {
  4661.           if (fill_size)
  4662.         memcpy (Data_Segment + i, fill_literal, fill_size);
  4663.           i += fill_size;
  4664.         }
  4665.     }
  4666.     }
  4667.  
  4668.  
  4669.   /*
  4670.    *    Generate the VMS object file records
  4671.    *    1st GSD then TIR records
  4672.    */
  4673.  
  4674.   /*******       Global Symbol Dictionary       *******/
  4675.   /*
  4676.    * Emit globalvalues now.  We must do this before the text psect
  4677.    * is defined, or we will get linker warnings about multiply defined
  4678.    * symbols.  All of the globalvalues "reference" psect 0, although
  4679.    * it really does not have anything to do with it.
  4680.    */
  4681.   VMS_Emit_Globalvalues (text_siz, data_siz, Data_Segment);
  4682.   /*
  4683.    *    Define the Text Psect
  4684.    */
  4685.   Text_Psect = Psect_Number++;
  4686.   VMS_Psect_Spec ("$code", text_siz, "TEXT", 0);
  4687.   /*
  4688.    *    Define the BSS Psect
  4689.    */
  4690.   if (bss_siz > 0)
  4691.     {
  4692.       Bss_Psect = Psect_Number++;
  4693.       VMS_Psect_Spec ("$uninitialized_data", bss_siz, "DATA", 0);
  4694.     }
  4695. #ifndef gxx_bug_fixed
  4696.   /* 
  4697.    * The g++ compiler does not write out external references to vtables
  4698.    * correctly.  Check for this and holler if we see it happening.
  4699.    * If that compiler bug is ever fixed we can remove this.
  4700.    */
  4701.   for (sp = symbol_rootP; sp; sp = symbol_next (sp)) 
  4702.     {
  4703.       /*
  4704.        *    Dispatch on symbol type
  4705.        */
  4706.       switch (S_GET_RAW_TYPE (sp)) {
  4707.     /*
  4708.      *    Global Reference
  4709.      */
  4710.       case N_UNDF:
  4711.     /*
  4712.      *    Make a GSD global symbol reference
  4713.      *    record.
  4714.      */
  4715.     if (strncmp (S_GET_NAME (sp),"__vt.",5) == 0)
  4716.       {
  4717.         S_GET_RAW_TYPE (sp) = N_UNDF | N_EXT;
  4718.         as_warn("g++ wrote an extern reference to %s as a routine.",
  4719.             S_GET_NAME (sp));
  4720.         as_warn("I will fix it, but I hope that it was not really a routine");
  4721.       };
  4722.     break;
  4723.       default:
  4724.     break;
  4725.       }
  4726.     }
  4727. #endif /* gxx_bug_fixed */
  4728.   /*
  4729.    *    Now scan the symbols and emit the appropriate GSD records
  4730.    */
  4731.   for (sp = symbol_rootP; sp; sp = symbol_next (sp))
  4732.     {
  4733.       /*
  4734.        *    Dispatch on symbol type
  4735.        */
  4736.       switch (S_GET_RAW_TYPE (sp))
  4737.     {
  4738.       /*
  4739.        *    Global uninitialized data
  4740.        */
  4741.     case N_UNDF | N_EXT:
  4742.       /*
  4743.        *    Make a VMS data symbol entry
  4744.        */
  4745.       vsp = (struct VMS_Symbol *)
  4746.         xmalloc (sizeof (*vsp));
  4747.       vsp->Symbol = sp;
  4748.       vsp->Size = S_GET_VALUE (sp);
  4749.       vsp->Psect_Index = Psect_Number++;
  4750.       vsp->Psect_Offset = 0;
  4751.       vsp->Next = VMS_Symbols;
  4752.       VMS_Symbols = vsp;
  4753.       sp->sy_number = (int) vsp;
  4754.       /*
  4755.        *    Make the psect for this data
  4756.        */
  4757.       if (S_GET_OTHER (sp))
  4758.         Globalref = VMS_Psect_Spec (
  4759.                      S_GET_NAME (sp),
  4760.                      vsp->Size,
  4761.                      "CONST",
  4762.                      vsp);
  4763.       else
  4764.         Globalref = VMS_Psect_Spec (
  4765.                      S_GET_NAME (sp),
  4766.                      vsp->Size,
  4767.                      "COMMON",
  4768.                      vsp);
  4769.       if (Globalref)
  4770.         Psect_Number--;
  4771.  
  4772. /* See if this is an external vtable.  We want to help the linker find
  4773.    these things in libraries, so we make a symbol reference.  This
  4774.    is not compatible with VAX-C usage for variables, but since vtables are
  4775.    only used internally by g++, we can get away with this hack.  */
  4776.  
  4777.       if(strncmp (S_GET_NAME (sp), "__vt.", 5) == 0)
  4778.         VMS_Global_Symbol_Spec (S_GET_NAME(sp),
  4779.                     vsp->Psect_Index,
  4780.                     0,
  4781.                     0);
  4782.  
  4783. #ifdef    NOT_VAX_11_C_COMPATIBLE
  4784.       /*
  4785.        *    Place a global symbol at the
  4786.        *    beginning of the Psect
  4787.        */
  4788.       VMS_Global_Symbol_Spec (S_GET_NAME (sp),
  4789.                   vsp->Psect_Index,
  4790.                   0,
  4791.                   1);
  4792. #endif    /* NOT_VAX_11_C_COMPATIBLE */
  4793.       break;
  4794.       /*
  4795.        *    Local uninitialized data
  4796.        */
  4797.     case N_BSS:
  4798.       /*
  4799.        *    Make a VMS data symbol entry
  4800.        */
  4801.       vsp = (struct VMS_Symbol *)
  4802.         xmalloc (sizeof (*vsp));
  4803.       vsp->Symbol = sp;
  4804.       vsp->Size = 0;
  4805.       vsp->Psect_Index = Bss_Psect;
  4806.       vsp->Psect_Offset =
  4807.         S_GET_VALUE (sp) -
  4808.         bss_address_frag.fr_address;
  4809.       vsp->Next = VMS_Symbols;
  4810.       VMS_Symbols = vsp;
  4811.       sp->sy_number = (int) vsp;
  4812.       break;
  4813.       /*
  4814.        *    Global initialized data
  4815.        */
  4816.     case N_DATA | N_EXT:
  4817.       /*
  4818.        *    Make a VMS data symbol entry
  4819.        */
  4820.       vsp = (struct VMS_Symbol *)
  4821.         xmalloc (sizeof (*vsp));
  4822.       vsp->Symbol = sp;
  4823.       vsp->Size = VMS_Initialized_Data_Size (sp,
  4824.                          text_siz + data_siz);
  4825.       vsp->Psect_Index = Psect_Number++;
  4826.       vsp->Psect_Offset = 0;
  4827.       vsp->Next = VMS_Symbols;
  4828.       VMS_Symbols = vsp;
  4829.       sp->sy_number = (int) vsp;
  4830.       /*
  4831.        *    Make its psect
  4832.        */
  4833.       if (S_GET_OTHER (sp))
  4834.         Globalref = VMS_Psect_Spec (
  4835.                      S_GET_NAME (sp),
  4836.                      vsp->Size,
  4837.                      "CONST",
  4838.                      vsp);
  4839.       else
  4840.         Globalref = VMS_Psect_Spec (
  4841.                      S_GET_NAME (sp),
  4842.                      vsp->Size,
  4843.                      "COMMON",
  4844.                      vsp);
  4845.       if (Globalref)
  4846.         Psect_Number--;
  4847.  
  4848. /* See if this is an external vtable.  We want to help the linker find
  4849.    these things in libraries, so we make a symbol definition.  This
  4850.    is not compatible with VAX-C usage for variables, but since vtables are
  4851.    only used internally by g++, we can get away with this hack.  */
  4852.  
  4853.       if(strncmp (S_GET_NAME (sp), "__vt.", 5) == 0)
  4854.         VMS_Global_Symbol_Spec (S_GET_NAME (sp),
  4855.                     vsp->Psect_Index,
  4856.                     0,
  4857.                     1);
  4858.  
  4859. #ifdef    NOT_VAX_11_C_COMPATIBLE
  4860.       /*
  4861.        *    Place a global symbol at the
  4862.        *    beginning of the Psect
  4863.        */
  4864.       VMS_Global_Symbol_Spec (S_GET_NAME (sp),
  4865.                   vsp->Psect_Index,
  4866.                   0,
  4867.                   1);
  4868. #endif    /* NOT_VAX_11_C_COMPATIBLE */
  4869.       break;
  4870.       /*
  4871.        *    Local initialized data
  4872.        */
  4873.     case N_DATA:
  4874.       /*
  4875.        *    Make a VMS data symbol entry
  4876.        */
  4877.       vsp = (struct VMS_Symbol *)
  4878.         xmalloc (sizeof (*vsp));
  4879.       vsp->Symbol = sp;
  4880.       vsp->Size =
  4881.         VMS_Initialized_Data_Size (sp,
  4882.                        text_siz + data_siz);
  4883.       vsp->Psect_Index = Data_Psect;
  4884.       vsp->Psect_Offset =
  4885.         Local_Initialized_Data_Size;
  4886.       Local_Initialized_Data_Size += vsp->Size;
  4887.       vsp->Next = VMS_Symbols;
  4888.       VMS_Symbols = vsp;
  4889.       sp->sy_number = (int) vsp;
  4890.       break;
  4891.       /*
  4892.        *    Global Text definition
  4893.        */
  4894.     case N_TEXT | N_EXT:
  4895.       {
  4896.         unsigned short Entry_Mask;
  4897.  
  4898.         /*
  4899.          *    Get the entry mask
  4900.          */
  4901.         fragP = sp->sy_frag;
  4902.         Entry_Mask = (fragP->fr_literal[0] & 0xff) +
  4903.           ((fragP->fr_literal[1] & 0xff)
  4904.            << 8);
  4905.         /*
  4906.          *    Define the Procedure entry pt.
  4907.          */
  4908.         VMS_Procedure_Entry_Pt (S_GET_NAME (sp),
  4909.                     Text_Psect,
  4910.                     S_GET_VALUE (sp),
  4911.                     Entry_Mask);
  4912.         break;
  4913.       }
  4914.       /*
  4915.        *    Local Text definition
  4916.        */
  4917.     case N_TEXT:
  4918.       /*
  4919.        *    Make a VMS data symbol entry
  4920.        */
  4921.       if (Text_Psect != -1)
  4922.         {
  4923.           vsp = (struct VMS_Symbol *)
  4924.         xmalloc (sizeof (*vsp));
  4925.           vsp->Symbol = sp;
  4926.           vsp->Size = 0;
  4927.           vsp->Psect_Index = Text_Psect;
  4928.           vsp->Psect_Offset = S_GET_VALUE (sp);
  4929.           vsp->Next = VMS_Symbols;
  4930.           VMS_Symbols = vsp;
  4931.           sp->sy_number = (int) vsp;
  4932.         }
  4933.       break;
  4934.       /*
  4935.        *    Global Reference
  4936.        */
  4937.     case N_UNDF:
  4938.       /*
  4939.        *    Make a GSD global symbol reference
  4940.        *    record.
  4941.        */
  4942.       VMS_Global_Symbol_Spec (S_GET_NAME (sp),
  4943.                   0,
  4944.                   0,
  4945.                   0);
  4946.       break;
  4947.       /*
  4948.        *    Anything else
  4949.        */
  4950.     default:
  4951.       /*
  4952.        *    Ignore STAB symbols
  4953.        *    Including .stabs emitted by g++
  4954.        */
  4955.       if (S_IS_DEBUG (sp) || (S_GET_TYPE (sp) == 22))
  4956.         break;
  4957.       /*
  4958.        *    Error
  4959.        */
  4960.       if (S_GET_TYPE (sp) != 22)
  4961.         printf (" ERROR, unknown type (%d)\n",
  4962.             S_GET_TYPE (sp));
  4963.       break;
  4964.     }
  4965.     }
  4966.   /*
  4967.    *    Define the Data Psect
  4968.    */
  4969.   if ((data_siz > 0) && (Local_Initialized_Data_Size > 0))
  4970.     {
  4971.       /*
  4972.        *    Do it
  4973.        */
  4974.       Data_Psect = Psect_Number++;
  4975.       VMS_Psect_Spec ("$data",
  4976.               Local_Initialized_Data_Size,
  4977.               "DATA", 0);
  4978.       /*
  4979.        *    Scan the VMS symbols and fill in the data psect
  4980.        */
  4981.       for (vsp = VMS_Symbols; vsp; vsp = vsp->Next)
  4982.     {
  4983.       /*
  4984.        *    Only look for undefined psects
  4985.        */
  4986.       if (vsp->Psect_Index < 0)
  4987.         {
  4988.           /*
  4989.            *    And only initialized data
  4990.            */
  4991.           if ((S_GET_TYPE (vsp->Symbol) == N_DATA) && !S_IS_EXTERNAL (vsp->Symbol))
  4992.         vsp->Psect_Index = Data_Psect;
  4993.         }
  4994.     }
  4995.     }
  4996.  
  4997.   /*******  Text Information and Relocation Records  *******/
  4998.   /*
  4999.    *    Write the text segment data
  5000.    */
  5001.   if (text_siz > 0)
  5002.     {
  5003.       /*
  5004.        *    Scan the text fragments
  5005.        */
  5006.       for (fragP = text_frag_root; fragP; fragP = fragP->fr_next)
  5007.     {
  5008.       /*
  5009.        *    Stop if we get to the data fragments
  5010.        */
  5011.       if (fragP == data_frag_root)
  5012.         break;
  5013.       /*
  5014.        *    Ignore fragments with no data
  5015.        */
  5016.       if ((fragP->fr_fix == 0) && (fragP->fr_var == 0))
  5017.         continue;
  5018.       /*
  5019.        *    Go the the appropriate offset in the
  5020.        *    Text Psect.
  5021.        */
  5022.       VMS_Set_Psect (Text_Psect, fragP->fr_address, OBJ_S_C_TIR);
  5023.       /*
  5024.        *    Store the "fixed" part
  5025.        */
  5026.       if (fragP->fr_fix)
  5027.         VMS_Store_Immediate_Data (fragP->fr_literal,
  5028.                       fragP->fr_fix,
  5029.                       OBJ_S_C_TIR);
  5030.       /*
  5031.        *    Store the "variable" part
  5032.        */
  5033.       if (fragP->fr_var && fragP->fr_offset)
  5034.         VMS_Store_Repeated_Data (fragP->fr_offset,
  5035.                      fragP->fr_literal +
  5036.                      fragP->fr_fix,
  5037.                      fragP->fr_var,
  5038.                      OBJ_S_C_TIR);
  5039.     }
  5040.       /*
  5041.        *    Now we go through the text segment fixups and
  5042.        *    generate TIR records to fix up addresses within
  5043.        *    the Text Psect
  5044.        */
  5045.       for (fixP = text_fix_root; fixP; fixP = fixP->fx_next)
  5046.     {
  5047.       /*
  5048.        *    We DO handle the case of "Symbol - Symbol" as
  5049.        *    long as it is in the same segment.
  5050.        */
  5051.       if (fixP->fx_subsy && fixP->fx_addsy)
  5052.         {
  5053.           int i;
  5054.  
  5055.           /*
  5056.            *    They need to be in the same segment
  5057.            */
  5058.           if (S_GET_RAW_TYPE (fixP->fx_subsy) !=
  5059.           S_GET_RAW_TYPE (fixP->fx_addsy))
  5060.         error ("Fixup data addsy and subsy didn't have the same type");
  5061.           /*
  5062.            *    And they need to be in one that we
  5063.            *    can check the psect on
  5064.            */
  5065.           if ((S_GET_TYPE (fixP->fx_addsy) != N_DATA) &&
  5066.           (S_GET_TYPE (fixP->fx_addsy) != N_TEXT))
  5067.         error ("Fixup data addsy and subsy didn't have an appropriate type");
  5068.           /*
  5069.            *    This had better not be PC relative!
  5070.            */
  5071.           if (fixP->fx_pcrel)
  5072.         error ("Fixup data was erroneously \"pcrel\"");
  5073.           /*
  5074.            *    Subtract their values to get the
  5075.            *    difference.
  5076.            */
  5077.           i = S_GET_VALUE (fixP->fx_addsy) -
  5078.         S_GET_VALUE (fixP->fx_subsy);
  5079.           /*
  5080.            *    Now generate the fixup object records
  5081.            *    Set the psect and store the data
  5082.            */
  5083.           VMS_Set_Psect (Text_Psect,
  5084.                  fixP->fx_where +
  5085.                  fixP->fx_frag->fr_address,
  5086.                  OBJ_S_C_TIR);
  5087.           VMS_Store_Immediate_Data (&i,
  5088.                     fixP->fx_size,
  5089.                     OBJ_S_C_TIR);
  5090.           /*
  5091.            *    Done
  5092.            */
  5093.           continue;
  5094.         }
  5095.       /*
  5096.        *    Size will HAVE to be "long"
  5097.        */
  5098.       if (fixP->fx_size != sizeof (long))
  5099.         error ("Fixup datum was not a longword");
  5100.       /*
  5101.        *    Symbol must be "added" (if it is ever
  5102.        *                subtracted we can
  5103.        *                fix this assumption)
  5104.        */
  5105.       if (fixP->fx_addsy == 0)
  5106.         error ("Fixup datum was not \"fixP->fx_addsy\"");
  5107.       /*
  5108.        *    Store the symbol value in a PIC fashion
  5109.        */
  5110.       VMS_Store_PIC_Symbol_Reference (fixP->fx_addsy,
  5111.                       fixP->fx_offset,
  5112.                       fixP->fx_pcrel,
  5113.                       Text_Psect,
  5114.                       fixP->fx_where +
  5115.                       fixP->fx_frag->fr_address,
  5116.                       OBJ_S_C_TIR);
  5117.       /*
  5118.        *    Check for indirect address reference,
  5119.        *    which has to be fixed up (as the linker
  5120.        *    will screw it up with TIR_S_C_STO_PICR).
  5121.        */
  5122.       if (fixP->fx_pcrel)
  5123.         VMS_Fix_Indirect_Reference (Text_Psect,
  5124.                     fixP->fx_where +
  5125.                     fixP->fx_frag->fr_address,
  5126.                     fixP->fx_frag,
  5127.                     text_frag_root);
  5128.     }
  5129.     }
  5130.   /*
  5131.    *    Store the Data segment:
  5132.    *
  5133.    *    Since this is REALLY hard to do any other way,
  5134.    *    we actually manufacture the data segment and
  5135.    *    the store the appropriate values out of it.
  5136.    *    The segment was manufactured before, now we just
  5137.    *    dump it into the appropriate psects.
  5138.    */
  5139.   if (data_siz > 0)
  5140.     {
  5141.  
  5142.       /*
  5143.        *    Now we can run through all the data symbols
  5144.        *    and store the data
  5145.        */
  5146.       for (vsp = VMS_Symbols; vsp; vsp = vsp->Next)
  5147.     {
  5148.       /*
  5149.        *    Ignore anything other than data symbols
  5150.        */
  5151.       if (S_GET_TYPE (vsp->Symbol) != N_DATA)
  5152.         continue;
  5153.       /*
  5154.        *    Set the Psect + Offset
  5155.        */
  5156.       VMS_Set_Psect (vsp->Psect_Index,
  5157.              vsp->Psect_Offset,
  5158.              OBJ_S_C_TIR);
  5159.       /*
  5160.        *    Store the data
  5161.        */
  5162.       VMS_Store_Immediate_Data (Data_Segment +
  5163.                     S_GET_VALUE (vsp->Symbol) -
  5164.                     text_siz,
  5165.                     vsp->Size,
  5166.                     OBJ_S_C_TIR);
  5167.     }
  5168.       /*
  5169.        *    Now we go through the data segment fixups and
  5170.        *    generate TIR records to fix up addresses within
  5171.        *    the Data Psects
  5172.        */
  5173.       for (fixP = data_fix_root; fixP; fixP = fixP->fx_next)
  5174.     {
  5175.       /*
  5176.        *    Find the symbol for the containing datum
  5177.        */
  5178.       for (vsp = VMS_Symbols; vsp; vsp = vsp->Next)
  5179.         {
  5180.           /*
  5181.            *    Only bother with Data symbols
  5182.            */
  5183.           sp = vsp->Symbol;
  5184.           if (S_GET_TYPE (sp) != N_DATA)
  5185.         continue;
  5186.           /*
  5187.            *    Ignore symbol if After fixup
  5188.            */
  5189.           if (S_GET_VALUE (sp) >
  5190.           (fixP->fx_where +
  5191.            fixP->fx_frag->fr_address))
  5192.         continue;
  5193.           /*
  5194.            *    See if the datum is here
  5195.            */
  5196.           if ((S_GET_VALUE (sp) + vsp->Size) <=
  5197.           (fixP->fx_where +
  5198.            fixP->fx_frag->fr_address))
  5199.         continue;
  5200.           /*
  5201.            *    We DO handle the case of "Symbol - Symbol" as
  5202.            *    long as it is in the same segment.
  5203.            */
  5204.           if (fixP->fx_subsy && fixP->fx_addsy)
  5205.         {
  5206.           int i;
  5207.  
  5208.           /*
  5209.            *    They need to be in the same segment
  5210.            */
  5211.           if (S_GET_RAW_TYPE (fixP->fx_subsy) !=
  5212.               S_GET_RAW_TYPE (fixP->fx_addsy))
  5213.             error ("Fixup data addsy and subsy didn't have the same type");
  5214.           /*
  5215.            *    And they need to be in one that we
  5216.            *    can check the psect on
  5217.            */
  5218.           if ((S_GET_TYPE (fixP->fx_addsy) != N_DATA) &&
  5219.               (S_GET_TYPE (fixP->fx_addsy) != N_TEXT))
  5220.             error ("Fixup data addsy and subsy didn't have an appropriate type");
  5221.           /*
  5222.            *    This had better not be PC relative!
  5223.            */
  5224.           if (fixP->fx_pcrel)
  5225.             error ("Fixup data was erroneously \"pcrel\"");
  5226.           /*
  5227.            *    Subtract their values to get the
  5228.            *    difference.
  5229.            */
  5230.           i = S_GET_VALUE (fixP->fx_addsy) -
  5231.             S_GET_VALUE (fixP->fx_subsy);
  5232.           /*
  5233.            *    Now generate the fixup object records
  5234.            *    Set the psect and store the data
  5235.            */
  5236.           VMS_Set_Psect (vsp->Psect_Index,
  5237.                  fixP->fx_frag->fr_address +
  5238.                  fixP->fx_where -
  5239.                  S_GET_VALUE (vsp->Symbol) +
  5240.                  vsp->Psect_Offset,
  5241.                  OBJ_S_C_TIR);
  5242.           VMS_Store_Immediate_Data (&i,
  5243.                         fixP->fx_size,
  5244.                         OBJ_S_C_TIR);
  5245.           /*
  5246.            *    Done
  5247.            */
  5248.           break;
  5249.         }
  5250.           /*
  5251.            *    Size will HAVE to be "long"
  5252.            */
  5253.           if (fixP->fx_size != sizeof (long))
  5254.         error ("Fixup datum was not a longword");
  5255.           /*
  5256.            *    Symbol must be "added" (if it is ever
  5257.            *                subtracted we can
  5258.            *                fix this assumption)
  5259.            */
  5260.           if (fixP->fx_addsy == 0)
  5261.         error ("Fixup datum was not \"fixP->fx_addsy\"");
  5262.           /*
  5263.            *    Store the symbol value in a PIC fashion
  5264.            */
  5265.           VMS_Store_PIC_Symbol_Reference (
  5266.                            fixP->fx_addsy,
  5267.                            fixP->fx_offset,
  5268.                            fixP->fx_pcrel,
  5269.                            vsp->Psect_Index,
  5270.                            fixP->fx_frag->fr_address +
  5271.                            fixP->fx_where -
  5272.                            S_GET_VALUE (vsp->Symbol) +
  5273.                            vsp->Psect_Offset,
  5274.                            OBJ_S_C_TIR);
  5275.           /*
  5276.            *    Done
  5277.            */
  5278.           break;
  5279.         }
  5280.  
  5281.     }
  5282.     }
  5283.  
  5284.   /*
  5285.    *    Write the Traceback Begin Module record
  5286.    */
  5287.   VMS_TBT_Module_Begin ();
  5288.   /*
  5289.    *    Scan the symbols and write out the routines
  5290.    *    (this makes the assumption that symbols are in
  5291.    *     order of ascending text segment offset)
  5292.    */
  5293.   {
  5294.     struct symbol *Current_Routine = 0;
  5295.     int Current_Line_Number = 0;
  5296.     int Current_Offset = -1;
  5297.     struct input_file *Current_File;
  5298.  
  5299. /* Output debugging info for global variables and static variables that are not
  5300.  * specific to one routine. We also need to examine all stabs directives, to
  5301.  * find the definitions to all of the advanced data types, and this is done by
  5302.  * VMS_LSYM_Parse.  This needs to be done before any definitions are output to
  5303.  * the object file, since there can be forward references in the stabs
  5304.  * directives. When through with parsing, the text of the stabs directive
  5305.  * is altered, with the definitions removed, so that later passes will see
  5306.  * directives as they would be written if the type were already defined.
  5307.  *
  5308.  * We also look for files and include files, and make a list of them.  We
  5309.  * examine the source file numbers to establish the actual lines that code was
  5310.  * generated from, and then generate offsets.
  5311.  */
  5312.     VMS_LSYM_Parse ();
  5313.     for (symbolP = symbol_rootP; symbolP; symbolP = symbol_next (symbolP))
  5314.       {
  5315.     /*
  5316.      *    Deal with STAB symbols
  5317.      */
  5318.     if (S_IS_DEBUG (symbolP))
  5319.       {
  5320.         /*
  5321.          *    Dispatch on STAB type
  5322.          */
  5323.         switch ((unsigned char) S_GET_RAW_TYPE (symbolP))
  5324.           {
  5325.           case N_SLINE:
  5326.         if (S_GET_DESC (symbolP) > Current_File->max_line)
  5327.           Current_File->max_line = S_GET_DESC (symbolP);
  5328.         if (S_GET_DESC (symbolP) < Current_File->min_line)
  5329.           Current_File->min_line = S_GET_DESC (symbolP);
  5330.         break;
  5331.           case N_SO:
  5332.         Current_File = find_file (symbolP);
  5333.         Current_File->flag = 1;
  5334.         Current_File->min_line = 1;
  5335.         break;
  5336.           case N_SOL:
  5337.         Current_File = find_file (symbolP);
  5338.         break;
  5339.           case N_GSYM:
  5340.         VMS_GSYM_Parse (symbolP, Text_Psect);
  5341.         break;
  5342.           case N_LCSYM:
  5343.         VMS_LCSYM_Parse (symbolP, Text_Psect);
  5344.         break;
  5345.           case N_FUN:    /* For static constant symbols */
  5346.           case N_STSYM:
  5347.         VMS_STSYM_Parse (symbolP, Text_Psect);
  5348.         break;
  5349.           }
  5350.       }
  5351.       }
  5352.  
  5353.     /* now we take a quick sweep through the files and assign offsets
  5354.     to each one.  This will essentially be the starting line number to the
  5355.    debugger for each file.  Output the info for the debugger to specify the
  5356.    files, and then tell it how many lines to use */
  5357.     {
  5358.       int File_Number = 0;
  5359.       int Debugger_Offset = 0;
  5360.       int file_available;
  5361.       Current_File = file_root;
  5362.       for (Current_File = file_root; Current_File; Current_File = Current_File->next)
  5363.     {
  5364.       if (Current_File == (struct input_file *) NULL)
  5365.         break;
  5366.       if (Current_File->max_line == 0)
  5367.         continue;
  5368.       if ((strncmp (Current_File->name, "GNU_GXX_INCLUDE:", 16) == 0) &&
  5369.           !flagseen['D'])
  5370.         continue;
  5371.       if ((strncmp (Current_File->name, "GNU_CC_INCLUDE:", 15) == 0) &&
  5372.           !flagseen['D'])
  5373.         continue;
  5374. /* show a few extra lines at the start of the region selected */
  5375.       if (Current_File->min_line > 2)
  5376.         Current_File->min_line -= 2;
  5377.       Current_File->offset = Debugger_Offset - Current_File->min_line + 1;
  5378.       Debugger_Offset += Current_File->max_line - Current_File->min_line + 1;
  5379.       if (Current_File->same_file_fpnt != (struct input_file *) NULL)
  5380.         Current_File->file_number = Current_File->same_file_fpnt->file_number;
  5381.       else
  5382.         {
  5383.           Current_File->file_number = ++File_Number;
  5384.           file_available = VMS_TBT_Source_File (Current_File->name,
  5385.                          Current_File->file_number);
  5386.           if (!file_available)
  5387.         {
  5388.           Current_File->file_number = 0;
  5389.           File_Number--;
  5390.           continue;
  5391.         };
  5392.         };
  5393.       VMS_TBT_Source_Lines (Current_File->file_number,
  5394.                 Current_File->min_line,
  5395.                Current_File->max_line - Current_File->min_line + 1);
  5396.     };            /* for */
  5397.     };                /* scope */
  5398.     Current_File = (struct input_file *) NULL;
  5399.  
  5400.     for (symbolP = symbol_rootP; symbolP; symbolP = symbol_next (symbolP))
  5401.       {
  5402.     /*
  5403.      *    Deal with text symbols
  5404.      */
  5405.     if (!S_IS_DEBUG (symbolP) && (S_GET_TYPE (symbolP) == N_TEXT))
  5406.       {
  5407.         /*
  5408.          *    Ignore symbols starting with "L",
  5409.          *    as they are local symbols
  5410.          */
  5411.         if (*S_GET_NAME (symbolP) == 'L')
  5412.           continue;
  5413.         /*
  5414.          *    If there is a routine start defined,
  5415.          *    terminate it.
  5416.          */
  5417.         if (Current_Routine)
  5418.           {
  5419.         /*
  5420.          *    End the routine
  5421.          */
  5422.         VMS_TBT_Routine_End (text_siz, Current_Routine);
  5423.           }
  5424.         /*
  5425.          *    Store the routine begin traceback info
  5426.          */
  5427.         if (Text_Psect != -1)
  5428.           {
  5429.         VMS_TBT_Routine_Begin (symbolP, Text_Psect);
  5430.         Current_Routine = symbolP;
  5431.           }
  5432. /* Output local symbols, i.e. all symbols that are associated with a specific
  5433.  * routine.  We output them now so the debugger recognizes them as local to
  5434.  * this routine.
  5435.  */
  5436.         {
  5437.           symbolS *symbolP1;
  5438.           char *pnt;
  5439.           char *pnt1;
  5440.           for (symbolP1 = Current_Routine; symbolP1; symbolP1 = symbol_next (symbolP1))
  5441.         {
  5442.           if (!S_IS_DEBUG (symbolP1))
  5443.             continue;
  5444.           if (S_GET_RAW_TYPE (symbolP1) != N_FUN)
  5445.             continue;
  5446.           pnt = S_GET_NAME (symbolP);
  5447.           pnt1 = S_GET_NAME (symbolP1);
  5448.           if (*pnt++ != '_')
  5449.             continue;
  5450.           while (*pnt++ == *pnt1++)
  5451.             {
  5452.             };
  5453.           if (*pnt1 != 'F' && *pnt1 != 'f') continue;
  5454.           if ((*(--pnt) == '\0') && (*(--pnt1) == ':'))
  5455.             break;
  5456.         };
  5457.           if (symbolP1 != (symbolS *) NULL)
  5458.         VMS_DBG_Define_Routine (symbolP1, Current_Routine, Text_Psect);
  5459.         }            /* local symbol block */
  5460.         /*
  5461.          *    Done
  5462.          */
  5463.         continue;
  5464.       }
  5465.     /*
  5466.      *    Deal with STAB symbols
  5467.      */
  5468.     if (S_IS_DEBUG (symbolP))
  5469.       {
  5470.         /*
  5471.          *    Dispatch on STAB type
  5472.          */
  5473.         switch ((unsigned char) S_GET_RAW_TYPE (symbolP))
  5474.           {
  5475.         /*
  5476.          *    Line number
  5477.          */
  5478.           case N_SLINE:
  5479.         /* Offset the line into the correct portion
  5480.          * of the file */
  5481.         if (Current_File->file_number == 0)
  5482.           break;
  5483.         /* Sometimes the same offset gets several source
  5484.          * lines assigned to it.
  5485.          * We should be selective about which lines
  5486.          * we allow, we should prefer lines that are
  5487.          * in the main source file when debugging
  5488.          * inline functions. */
  5489.         if ((Current_File->file_number != 1) &&
  5490.             S_GET_VALUE (symbolP) ==
  5491.             Current_Offset)
  5492.           break;
  5493.         /* calculate actual debugger source line */
  5494.         S_GET_DESC (symbolP)
  5495.           += Current_File->offset;
  5496.         /*
  5497.          *    If this is the 1st N_SLINE, setup
  5498.          *    PC/Line correlation.  Otherwise
  5499.          *    do the delta PC/Line.  If the offset
  5500.          *    for the line number is not +ve we need
  5501.          *    to do another PC/Line correlation
  5502.          *    setup
  5503.          */
  5504.         if (Current_Offset == -1)
  5505.           {
  5506.             VMS_TBT_Line_PC_Correlation (
  5507.                           S_GET_DESC (symbolP),
  5508.                           S_GET_VALUE (symbolP),
  5509.                           Text_Psect,
  5510.                           0);
  5511.           }
  5512.         else
  5513.           {
  5514.             if ((S_GET_DESC (symbolP) -
  5515.              Current_Line_Number) <= 0)
  5516.               {
  5517.             /*
  5518.              *    Line delta is not +ve, we
  5519.              *    need to close the line and
  5520.              *    start a new PC/Line
  5521.              *    correlation.
  5522.              */
  5523.             VMS_TBT_Line_PC_Correlation (0,
  5524.                              S_GET_VALUE (symbolP) -
  5525.                              Current_Offset,
  5526.                              0,
  5527.                              -1);
  5528.             VMS_TBT_Line_PC_Correlation (
  5529.                               S_GET_DESC (symbolP),
  5530.                               S_GET_VALUE (symbolP),
  5531.                               Text_Psect,
  5532.                               0);
  5533.               }
  5534.             else
  5535.               {
  5536.             /*
  5537.              *    Line delta is +ve, all is well
  5538.              */
  5539.             VMS_TBT_Line_PC_Correlation (
  5540.                               S_GET_DESC (symbolP) -
  5541.                               Current_Line_Number,
  5542.                               S_GET_VALUE (symbolP) -
  5543.                               Current_Offset,
  5544.                               0,
  5545.                               1);
  5546.               }
  5547.           }
  5548.         /*
  5549.          *    Update the current line/PC
  5550.          */
  5551.         Current_Line_Number = S_GET_DESC (symbolP);
  5552.         Current_Offset = S_GET_VALUE (symbolP);
  5553.         /*
  5554.          *    Done
  5555.          */
  5556.         break;
  5557.         /*
  5558.          *    Source file
  5559.          */
  5560.           case N_SO:
  5561.         /*
  5562.          *    Remember that we had a source file
  5563.          *    and emit the source file debugger
  5564.          *    record
  5565.          */
  5566.         Current_File =
  5567.           find_file (symbolP);
  5568.         break;
  5569. /* We need to make sure that we are really in the actual source file when
  5570.  * we compute the maximum line number.  Otherwise the debugger gets really
  5571.  * confused */
  5572.           case N_SOL:
  5573.         Current_File =
  5574.           find_file (symbolP);
  5575.         break;
  5576.           }
  5577.       }
  5578.       }
  5579.     /*
  5580.      *    If there is a routine start defined,
  5581.      *    terminate it (and the line numbers)
  5582.      */
  5583.     if (Current_Routine)
  5584.       {
  5585.     /*
  5586.      *    Terminate the line numbers
  5587.      */
  5588.     VMS_TBT_Line_PC_Correlation (0,
  5589.                    text_siz - S_GET_VALUE (Current_Routine),
  5590.                      0,
  5591.                      -1);
  5592.     /*
  5593.      *    Terminate the routine
  5594.      */
  5595.     VMS_TBT_Routine_End (text_siz, Current_Routine);
  5596.       }
  5597.   }
  5598.   /*
  5599.    *    Write the Traceback End Module TBT record
  5600.    */
  5601.   VMS_TBT_Module_End ();
  5602.  
  5603.   /*
  5604.    *    Write the End Of Module record
  5605.    */
  5606.   if (Entry_Point_Symbol == 0)
  5607.     Write_VMS_EOM_Record (-1, 0);
  5608.   else
  5609.     Write_VMS_EOM_Record (Text_Psect,
  5610.               S_GET_VALUE (Entry_Point_Symbol));
  5611.  
  5612.   /*
  5613.    *    All done, close the object file
  5614.    */
  5615.   Close_VMS_Object_File ();
  5616. }
  5617.  
  5618. /* end of obj-vms.c */
  5619.